From 3f250cab48bcbe3be0515d9ea4b545132a2b60b8 Mon Sep 17 00:00:00 2001 From: Philip Smart Date: Fri, 19 Jun 2020 01:14:08 +0100 Subject: [PATCH] Further updates for the MZ-700 mode and NASCOM basic --- common/tranzputer.c | 454 +++++++++++++++++++++++--------- include/tranzputer.h | 26 +- libraries/lib/libimath2-k64f.a | Bin 12504 -> 12504 bytes libraries/lib/libumansi-k64f.a | Bin 124218 -> 124218 bytes libraries/lib/libummath-k64f.a | Bin 2660 -> 2660 bytes libraries/lib/libummathf-k64f.a | Bin 63972 -> 63972 bytes libraries/lib/libummisc-k64f.a | Bin 6222 -> 6222 bytes libraries/lib/libumstdio-k64f.a | Bin 80050 -> 80050 bytes zOS/Makefile.k64f | 2 +- zOS/src/zOS.cpp | 4 +- 10 files changed, 351 insertions(+), 135 deletions(-) diff --git a/common/tranzputer.c b/common/tranzputer.c index 637019e..cc01099 100644 --- a/common/tranzputer.c +++ b/common/tranzputer.c @@ -2904,13 +2904,29 @@ void svcSetDefaults(enum FILE_TYPE type) switch(type) { case CAS: - strcpy((char *)svcControl.directory, TZSVC_DEFAULT_CAS_DIR); - strcpy((char *)svcControl.wildcard, TZSVC_DEFAULT_WILDCARD); + // If there is no directory path, use the inbuilt default. + if(svcControl.directory[0] == '\0') + { + strcpy((char *)svcControl.directory, TZSVC_DEFAULT_CAS_DIR); + } + // If there is no wildcard matching, use default. + if(svcControl.wildcard[0] == '\0') + { + strcpy((char *)svcControl.wildcard, TZSVC_DEFAULT_WILDCARD); + } break; case BAS: - strcpy((char *)svcControl.directory, TZSVC_DEFAULT_BAS_DIR); - strcpy((char *)svcControl.wildcard, TZSVC_DEFAULT_WILDCARD); + // If there is no directory path, use the inbuilt default. + if(svcControl.directory[0] == '\0') + { + strcpy((char *)svcControl.directory, TZSVC_DEFAULT_BAS_DIR); + } + // If there is no wildcard matching, use default. + if(svcControl.wildcard[0] == '\0') + { + strcpy((char *)svcControl.wildcard, TZSVC_DEFAULT_WILDCARD); + } break; case MZF: @@ -2949,7 +2965,7 @@ static uint32_t getNextChar(const char** ptr) // Match an MZF name with a given wildcard. // This method originated from the private method in FatFS but adapted to work with MZF filename matching. // Input: wildcard - Pattern to match -// fileName - MZF fileName, either CR or NUL terminated or MZF_FILENAME_LEN chars long. +// fileName - MZF fileName, either CR or NUL terminated or TZSVC_FILENAME_SIZE chars long. // skip - Number of characters to skip due to ?'s // infinite - Infinite search as * specified. // Output: 0 - No match @@ -2995,7 +3011,7 @@ static int matchFileWithWildcard(const char *pattern, const char *fileName, int // End of filename, Sharp filenames can be terminated with 0x00, CR or size. If we get to the end of the name then it is // a match. // - if((np - fileName) == MZF_FILENAME_LEN) return 1; + if((np - fileName) == TZSVC_FILENAME_SIZE) return 1; // Get a pattern char pc = getNextChar(&pp); @@ -3017,7 +3033,7 @@ static int matchFileWithWildcard(const char *pattern, const char *fileName, int getNextChar(&fileName); /* Retry until end of name if infinite search is specified */ - } while (infinite && nc != 0x00 && nc != 0x0d && (np - fileName) < MZF_FILENAME_LEN); + } while (infinite && nc != 0x00 && nc != 0x0d && (np - fileName) < TZSVC_FILENAME_SIZE); return 0; } @@ -3030,7 +3046,7 @@ static int matchFileWithWildcard(const char *pattern, const char *fileName, int // // The parameters are passed in the svcControl block. // -uint8_t svcReadDir(uint8_t mode) +uint8_t svcReadDir(uint8_t mode, enum FILE_TYPE type) { // Locals - dont use global as this is a seperate thread. // @@ -3049,11 +3065,11 @@ uint8_t svcReadDir(uint8_t mode) { // Close if previously open. if(dirOpen == 1) - svcReadDir(TZSVC_CLOSE); + svcReadDir(TZSVC_CLOSE, type); // Setup the defaults // - svcSetDefaults(MZF); + svcSetDefaults(type); // Open the directory. result = f_opendir(&dirFp, (char *)&svcControl.directory); @@ -3063,7 +3079,7 @@ uint8_t svcReadDir(uint8_t mode) // dirOpen = 1; dirSector = 0; - result = (FRESULT)svcReadDir(TZSVC_NEXT); + result = (FRESULT)svcReadDir(TZSVC_NEXT, type); } } @@ -3078,14 +3094,14 @@ uint8_t svcReadDir(uint8_t mode) // if(dirSector < svcControl.dirSector) { - result=svcReadDir(TZSVC_OPEN); + result=svcReadDir(TZSVC_OPEN, type); } if(!result) { // Now get the sector by advancement. for(uint8_t idx=dirSector; idx < svcControl.dirSector && result == FR_OK; idx++) { - result=svcReadDir(TZSVC_NEXT); + result=svcReadDir(TZSVC_NEXT, type); } } } @@ -3109,33 +3125,92 @@ uint8_t svcReadDir(uint8_t mode) // If an error occurs or we are at the end of the directory listing close the sector and pass back. if(result != FR_OK || fno.fname[0] == 0) break; - // Check to see if this is a valid MZF file. + // Check to see if this is a valid file for the given type. const char *ext = strrchr(fno.fname, '.'); - if(!ext || strcasecmp(++ext, TZSVC_DEFAULT_MZF_EXT) != 0) + if(type == MZF && (!ext || strcasecmp(++ext, TZSVC_DEFAULT_MZF_EXT) != 0)) + continue; + if(type == BAS && (!ext || strcasecmp(++ext, TZSVC_DEFAULT_BAS_EXT) != 0)) + continue; + if(type == CAS && (!ext || strcasecmp(++ext, TZSVC_DEFAULT_CAS_EXT) != 0)) + continue; + if(type == ALL && !ext) continue; - // Build filename. + // Sharp files need special handling, the file needs te opened and the Sharp filename read out, this is then returned as the filename. // - sprintf(fqfn, "0:\\%s\\%s", svcControl.directory, fno.fname); - - // Open the file so we can read out the MZF header which is the information TZFS/CPM needs. - // - result = f_open(&File, fqfn, FA_OPEN_EXISTING | FA_READ); - - // If no error occurred, read in the header. - // - if(!result) result = f_read(&File, (char *)&dirBlock->dirEnt[idx], TZSVC_CMPHDR_SIZE, &readSize); - - // No errors, read the header. - if(!result && readSize == TZSVC_CMPHDR_SIZE) + if(type == MZF) + { + // Build filename. + // + sprintf(fqfn, "0:\\%s\\%s", svcControl.directory, fno.fname); + + // Open the file so we can read out the MZF header which is the information TZFS/CPM needs. + // + result = f_open(&File, fqfn, FA_OPEN_EXISTING | FA_READ); + + // If no error occurred, read in the header. + // + if(!result) result = f_read(&File, (char *)&dirBlock->dirEnt[idx], TZSVC_CMPHDR_SIZE, &readSize); + + // No errors, read the header. + if(!result && readSize == TZSVC_CMPHDR_SIZE) + { + // Close the file, no longer needed. + f_close(&File); + + // Check to see if the file matches any given wildcard. + // + if(matchFileWithWildcard((char *)&svcControl.wildcard, (char *)&dirBlock->dirEnt[idx].fileName, 0, 0)) + { + // Valid so find next entry. + idx++; + } else + { + // Scrub the entry, not valid. + memset((char *)&dirBlock->dirEnt[idx], 0x00, TZSVC_CMPHDR_SIZE); + } + } + } else { - // Close the file, no longer needed. - f_close(&File); - // Check to see if the file matches any given wildcard. // - if(matchFileWithWildcard((char *)&svcControl.wildcard, (char *)&dirBlock->dirEnt[idx].fileName, 0, 0)) + if(matchFileWithWildcard((char *)&svcControl.wildcard, fno.fname, 0, 0)) { + // If the type is ALL FORMATTED then output a truncated directory entry formatted for display. + // + if(type == ALLFMT) + { + // Get the address of the file extension. + char *ext = strrchr(fno.fname, '.'); + + // Although not as efficient, maintain the use of the Sharp MZF header for normal directory filenames just use the extra space for increased filename size. + if(ext) + { + // Although not as efficient, maintain the use of the Sharp MZF header for normal directory filenames just use the extra space for increased filename size. + if((ext - fno.fname) > TZSVC_LONG_FMT_FNAME_SIZE-5) + { + fno.fname[TZSVC_LONG_FMT_FNAME_SIZE-6] = '*'; // Place a '*' to show the filename was truncated. + fno.fname[TZSVC_LONG_FMT_FNAME_SIZE-5] = 0x00; + } + *ext = 0x00; + ext++; + + sprintf((char *)&dirBlock->dirEnt[idx].fileName, "%-*s.%3s", TZSVC_LONG_FMT_FNAME_SIZE-5, fno.fname, ext); + } else + { + fno.fname[TZSVC_LONG_FMT_FNAME_SIZE] = 0x00; + strncpy((char *)&dirBlock->dirEnt[idx].fileName, fno.fname, TZSVC_LONG_FMT_FNAME_SIZE); + } + } else + // All other types just output the filename upto the limit truncating as necessary. + { + fno.fname[TZSVC_LONG_FNAME_SIZE] = 0x00; + strncpy((char *)&dirBlock->dirEnt[idx].fileName, fno.fname, TZSVC_LONG_FNAME_SIZE); + } + + // Set the attribute in the directory record to indicate this is a valid record. + dirBlock->dirEnt[idx].attr = 0xff; + // Valid so find next entry. idx++; } else @@ -3165,11 +3240,12 @@ uint8_t svcReadDir(uint8_t mode) } -// A method to find a file either using the Sharp MZ80A name or a number assigned to a directory listing. -// It is a bit long winded as each file that matches the filename specification has to be opened and the MZF header filename -// has to be checked. Cacheing would help here but wasteful in resources for number of times it would be called. +// A method to find a file either using a Sharp MZ80A name, a standard filename or a number assigned to a directory listing. +// For the Sharp MZ80A it is a bit long winded as each file that matches the filename specification has to be opened and the MZF header filename +// has to be checked. For standard files it is just a matter of matching the name. For both types a short cut is a number which is a files position +// in a directory obtained from a previous directory listing. // -uint8_t svcFindFile(char *file, char *searchFile, uint8_t searchNo) +uint8_t svcFindFile(char *file, char *searchFile, uint8_t searchNo, enum FILE_TYPE type) { // Locals uint8_t fileNo = 0; @@ -3184,7 +3260,7 @@ uint8_t svcFindFile(char *file, char *searchFile, uint8_t searchNo) // Setup the defaults // - svcSetDefaults(MZF); + svcSetDefaults(type); // Open the directory. result = f_opendir(&dirFp, (char *)&svcControl.directory); @@ -3200,39 +3276,76 @@ uint8_t svcFindFile(char *file, char *searchFile, uint8_t searchNo) // If an error occurs or we are at the end of the directory listing close the sector and pass back. if(result != FR_OK || fno.fname[0] == 0) break; - // Check to see if this is a valid MZF file. + // Check to see if this is a valid file for the given type. const char *ext = strrchr(fno.fname, '.'); - if(!ext || strcasecmp(++ext, TZSVC_DEFAULT_MZF_EXT) != 0) + if(type == MZF && (!ext || strcasecmp(++ext, TZSVC_DEFAULT_MZF_EXT) != 0)) continue; - - // Build filename. + if(type == BAS && (!ext || strcasecmp(++ext, TZSVC_DEFAULT_BAS_EXT) != 0)) + continue; + if(type == CAS && (!ext || strcasecmp(++ext, TZSVC_DEFAULT_CAS_EXT) != 0)) + continue; + if(type == ALL && !ext) + continue; + + // Sharp files need special handling, the file needs te opened and the Sharp filename read out, this is then used as the filename for matching. // - sprintf(fqfn, "0:\\%s\\%s", svcControl.directory, fno.fname); - - // Open the file so we can read out the MZF header which is the information TZFS/CPM needs. - // - result = f_open(&File, fqfn, FA_OPEN_EXISTING | FA_READ); - - // If no error occurred, read in the header. - // - if(!result) result = f_read(&File, (char *)&dirEnt, TZSVC_CMPHDR_SIZE, &readSize); - - // No errors, read the header. - if(!result && readSize == TZSVC_CMPHDR_SIZE) + if(type == MZF) + { + // Build filename. + // + sprintf(fqfn, "0:\\%s\\%s", svcControl.directory, fno.fname); + + // Open the file so we can read out the MZF header which is the information TZFS/CPM needs. + // + result = f_open(&File, fqfn, FA_OPEN_EXISTING | FA_READ); + + // If no error occurred, read in the header. + // + if(!result) result = f_read(&File, (char *)&dirEnt, TZSVC_CMPHDR_SIZE, &readSize); + + // No errors, read the header. + if(!result && readSize == TZSVC_CMPHDR_SIZE) + { + // Close the file, no longer needed. + f_close(&File); + + // Check to see if the file matches any given wildcard. If we dont have a match loop to next directory entry. + // + if(matchFileWithWildcard((char *)&svcControl.wildcard, (char *)&dirEnt.fileName, 0, 0)) + { + // If a filename has been given, see if this file matches it. + if(searchFile != NULL) + { + // Check to see if the file matches the name given with wildcard expansion if needed. + // + if(matchFileWithWildcard(searchFile, (char *)&dirEnt.fileName, 0, 0)) + { + found = 2; + } + } + + // If we are searching on file number and the latest directory entry retrieval matches, exit and return the filename. + if(searchNo != 0xFF && fileNo == (uint8_t)searchNo) + { + found = 1; + } else + { + fileNo++; + } + } + } + } else { - // Close the file, no longer needed. - f_close(&File); - // Check to see if the file matches any given wildcard. If we dont have a match loop to next directory entry. // - if(matchFileWithWildcard((char *)&svcControl.wildcard, (char *)&dirEnt.fileName, 0, 0)) + if(matchFileWithWildcard((char *)&svcControl.wildcard, (char *)&fno.fname, 0, 0)) { // If a filename has been given, see if this file matches it. if(searchFile != NULL) { // Check to see if the file matches the name given with wildcard expansion if needed. // - if(matchFileWithWildcard(searchFile, (char *)&dirEnt.fileName, 0, 0)) + if(matchFileWithWildcard(searchFile, (char *)&fno.fname, 0, 0)) { found = 2; } @@ -3265,7 +3378,7 @@ uint8_t svcFindFile(char *file, char *searchFile, uint8_t searchNo) // Method to read the current directory from the cache. If the cache is invalid resort to using the standard direct method. // -uint8_t svcReadDirCache(uint8_t mode) +uint8_t svcReadDirCache(uint8_t mode, enum FILE_TYPE type) { // Locals - dont use global as this is a seperate thread. // @@ -3277,13 +3390,17 @@ uint8_t svcReadDirCache(uint8_t mode) // Setup the defaults // - svcSetDefaults(MZF); + svcSetDefaults(type); + + // Need to refresh cache directory? + if(!osControl.dirMap.valid || strcasecmp((const char *)svcControl.directory, osControl.dirMap.directory) != 0 || osControl.dirMap.type != type) + result=svcCacheDir((const char *)svcControl.directory, svcControl.fileType, 0); // If there is no cache revert to direct directory read. // - if(!osControl.dirMap.valid) + if(!osControl.dirMap.valid || result) { - result = svcReadDir(mode); + result = svcReadDir(mode, type); } else { // Request to open? No need with cache, just return next block. @@ -3294,7 +3411,7 @@ uint8_t svcReadDirCache(uint8_t mode) dirOpen = 1; dirSector = 0; dirEntry = 0; - result = (FRESULT)svcReadDirCache(TZSVC_NEXT); + result = (FRESULT)svcReadDirCache(TZSVC_NEXT, type); } // Read a block of directory entries into the z80 service buffer sector. @@ -3323,16 +3440,63 @@ uint8_t svcReadDirCache(uint8_t mode) { // Check to see if the file matches any given wildcard. // - if(matchFileWithWildcard((char *)&svcControl.wildcard, (char *)&osControl.dirMap.file[dirEntry]->mzfHeader.fileName, 0, 0)) + if(matchFileWithWildcard((char *)&svcControl.wildcard, type == MZF ? (char *)&osControl.dirMap.mzfFile[dirEntry]->mzfHeader.fileName : (char *)osControl.dirMap.sdFileName[dirEntry], 0, 0)) { - // Valid so store and find next entry. + // Sharp files we copy the whole header into the entry. // - memcpy((char *)&dirBlock->dirEnt[idx], (char *)&osControl.dirMap.file[dirEntry]->mzfHeader, TZSVC_CMPHDR_SIZE); + if(type == MZF) + { + // Valid so store and find next entry. + // + memcpy((char *)&dirBlock->dirEnt[idx], (char *)&osControl.dirMap.mzfFile[dirEntry]->mzfHeader, TZSVC_CMPHDR_SIZE); + } else + { + // If the type is ALL FORMATTED then output a truncated directory entry formatted for display. + // + if(type == ALLFMT) + { + // Duplicate the cache entry, formatting is destructuve and less time neeed to duplicate than repair. + char *fname = strdup((char *)osControl.dirMap.sdFileName[dirEntry]); + if(fname != NULL) + { + // Get the address of the file extension. + char *ext = strrchr(fname, '.'); + + // Although not as efficient, maintain the use of the Sharp MZF header for normal directory filenames just use the extra space for increased filename size. + if(ext) + { + // Although not as efficient, maintain the use of the Sharp MZF header for normal directory filenames just use the extra space for increased filename size. + if((ext - fname) > TZSVC_LONG_FMT_FNAME_SIZE-5) + { + fname[TZSVC_LONG_FMT_FNAME_SIZE-6] = '*'; // Place a '*' to show the filename was truncated. + fname[TZSVC_LONG_FMT_FNAME_SIZE-5] = 0x00; + } + *ext = 0x00; + ext++; + sprintf((char *)&dirBlock->dirEnt[idx].fileName, "%-*s.%3s", TZSVC_LONG_FMT_FNAME_SIZE-5, fname, ext); + } else + { + fname[TZSVC_LONG_FMT_FNAME_SIZE] = 0x00; + strncpy((char *)&dirBlock->dirEnt[idx].fileName, fname, TZSVC_LONG_FMT_FNAME_SIZE); + } + + // Release the duplicate memory. + free(fname); + } else + { + printf("Out of memory duplicating directory filename.\n"); + } + } else + // All other types just output the filename upto the limit truncating as necessary. + { + osControl.dirMap.sdFileName[dirEntry][TZSVC_LONG_FNAME_SIZE] = 0x00; + strncpy((char *)&dirBlock->dirEnt[idx].fileName, (char *)osControl.dirMap.sdFileName[dirEntry], TZSVC_LONG_FNAME_SIZE); + } + + // Set the attribute in the directory record to indicate this is a valid record. + dirBlock->dirEnt[idx].attr = 0xff; + } idx++; - } else - { - // Scrub the entry, not valid. - memset((char *)&dirBlock->dirEnt[idx], 0x00, TZSVC_CMPHDR_SIZE); } dirEntry++; } @@ -3355,7 +3519,7 @@ uint8_t svcReadDirCache(uint8_t mode) // A method to find a file using the cached directory. If the cache is not available (ie. no memory) use the standard method. // -uint8_t svcFindFileCache(char *file, char *searchFile, uint8_t searchNo) +uint8_t svcFindFileCache(char *file, char *searchFile, uint8_t searchNo, enum FILE_TYPE type) { // Locals uint8_t fileNo = 0; @@ -3367,13 +3531,13 @@ uint8_t svcFindFileCache(char *file, char *searchFile, uint8_t searchNo) // if(!osControl.dirMap.valid) { - result = svcFindFile(file, searchFile, searchNo); + result = svcFindFile(file, searchFile, searchNo, type); } else { // If we are searching on file number and there is no filter in place, see if it is valid and exit with data. if(searchNo != 0xFF && strcmp((char *)svcControl.wildcard, TZSVC_DEFAULT_WILDCARD) == 0) { - if(searchNo < osControl.dirMap.entries && osControl.dirMap.file[searchNo]) + if(searchNo < osControl.dirMap.entries && osControl.dirMap.mzfFile[searchNo]) // <- this is the same for standard files as mzfFile is a union for sdFileName { found = 1; idx = searchNo; @@ -3386,14 +3550,14 @@ uint8_t svcFindFileCache(char *file, char *searchFile, uint8_t searchNo) do { // Check to see if the file matches any given wildcard. If we dont have a match loop to next directory entry. // - if(matchFileWithWildcard((char *)&svcControl.wildcard, (char *)&osControl.dirMap.file[idx]->mzfHeader.fileName, 0, 0)) + if(matchFileWithWildcard((char *)&svcControl.wildcard, type == MZF ? (char *)&osControl.dirMap.mzfFile[idx]->mzfHeader.fileName : (char *)&osControl.dirMap.sdFileName[idx], 0, 0)) { // If a filename has been given, see if this file matches it. if(searchFile != NULL) { // Check to see if the file matches the name given with wildcard expansion if needed. // - if(matchFileWithWildcard(searchFile, (char *)&osControl.dirMap.file[idx]->mzfHeader.fileName, 0, 0)) + if(matchFileWithWildcard(searchFile, type == MZF ? (char *)&osControl.dirMap.mzfFile[idx]->mzfHeader.fileName : (char *)&osControl.dirMap.sdFileName[idx], 0, 0)) { found = 2; } @@ -3421,7 +3585,7 @@ uint8_t svcFindFileCache(char *file, char *searchFile, uint8_t searchNo) { // Build filename. // - sprintf(file, "0:\\%s\\%s", osControl.dirMap.directory, osControl.dirMap.file[idx]->sdFileName); + sprintf(file, "0:\\%s\\%s", osControl.dirMap.directory, type == MZF ? osControl.dirMap.mzfFile[idx]->sdFileName : osControl.dirMap.sdFileName[idx]); } } @@ -3430,10 +3594,10 @@ uint8_t svcFindFileCache(char *file, char *searchFile, uint8_t searchNo) return(result == FR_OK ? (found == 0 ? 0 : 1) : 0); } -// Method to build up a cache of all the files on the SD card in a given directory along with the Sharp MZ80A header to which they map. -// This involves scanning each file to extract the MZF header and creating a map. +// Method to build up a cache of all the files on the SD card in a given directory along with any mapping to Sharp MZ80A headers if required. +// For Sharp MZ80A files this involves scanning each file to extract the MZF header and creating a map. // -uint8_t svcCacheDir(const char *directory, uint8_t force) +uint8_t svcCacheDir(const char *directory, enum FILE_TYPE type, uint8_t force) { // Locals uint8_t fileNo = 0; @@ -3446,7 +3610,7 @@ uint8_t svcCacheDir(const char *directory, uint8_t force) t_svcCmpDirEnt dirEnt; // No need to cache directory if we have already cached it. - if(force == 0 && osControl.dirMap.valid && strcasecmp(directory, osControl.dirMap.directory) == 0) + if(force == 0 && osControl.dirMap.valid && strcasecmp(directory, osControl.dirMap.directory) == 0 && osControl.dirMap.type == type) return(1); // Invalidate the map and free existing memory incase of errors. @@ -3454,14 +3618,19 @@ uint8_t svcCacheDir(const char *directory, uint8_t force) osControl.dirMap.valid = 0; for(uint8_t idx=0; idx < osControl.dirMap.entries; idx++) { - if(osControl.dirMap.file[idx]) + if(osControl.dirMap.type == MZF && osControl.dirMap.mzfFile[idx]) { - free(osControl.dirMap.file[idx]->sdFileName); - free(osControl.dirMap.file[idx]); - osControl.dirMap.file[idx] = 0; + free(osControl.dirMap.mzfFile[idx]->sdFileName); + free(osControl.dirMap.mzfFile[idx]); + osControl.dirMap.mzfFile[idx] = 0; + } else + { + free(osControl.dirMap.sdFileName[idx]); + osControl.dirMap.sdFileName[idx] = 0; } } osControl.dirMap.entries = 0; + osControl.dirMap.type = MZF; // Open the directory and extract all files. result = f_opendir(&dirFp, directory); @@ -3470,63 +3639,100 @@ uint8_t svcCacheDir(const char *directory, uint8_t force) fileNo = 0; do { - // Read an SD directory entry then open the returned SD file so that we can to read out the important MZF data for name matching. + // Read an SD directory entry. If reading Sharp MZ80A files then open the returned SD file so that we can to read out the important MZF data for name matching. // result = f_readdir(&dirFp, &fno); // If an error occurs or we are at the end of the directory listing close the sector and pass back. if(result != FR_OK || fno.fname[0] == 0) break; - // Check to see if this is a valid MZF file. + // Check to see if this is a valid file for the given type. const char *ext = strrchr(fno.fname, '.'); - if(!ext || strcasecmp(++ext, TZSVC_DEFAULT_MZF_EXT) != 0) + if(type == MZF && (!ext || strcasecmp(++ext, TZSVC_DEFAULT_MZF_EXT) != 0)) + continue; + if(type == BAS && (!ext || strcasecmp(++ext, TZSVC_DEFAULT_BAS_EXT) != 0)) + continue; + if(type == CAS && (!ext || strcasecmp(++ext, TZSVC_DEFAULT_CAS_EXT) != 0)) + continue; + if(type == ALL && !ext) continue; - // Build filename. + // Sharp files need special handling, the file needs te opened and the Sharp filename read out, this is then used in the cache. // - sprintf(fqfn, "0:\\%s\\%s", directory, fno.fname); - - // Open the file so we can read out the MZF header which is the information TZFS/CPM needs. - // - result = f_open(&File, fqfn, FA_OPEN_EXISTING | FA_READ); - - // If no error occurred, read in the header. - // - if(!result) result = f_read(&File, (char *)&dirEnt, TZSVC_CMPHDR_SIZE, &readSize); - - // No errors, read the header. - if(!result && readSize == TZSVC_CMPHDR_SIZE) + if(type == MZF) { - // Close the file, no longer needed. - f_close(&File); + // Build filename. + // + sprintf(fqfn, "0:\\%s\\%s", directory, fno.fname); - // Cache this entry. The SD filename is dynamically allocated as it's size can be upto 255 characters for LFN names. The Sharp name is - // fixed at 17 characters as you cant reliably rely on terminators and the additional data makes it a constant 32 chars long. - osControl.dirMap.file[fileNo] = (t_sharpToSDMap *)malloc(sizeof(t_sharpToSDMap)); - osControl.dirMap.file[fileNo]->sdFileName = (uint8_t *)malloc(strlen(fno.fname)+1); + // Open the file so we can read out the MZF header which is the information TZFS/CPM needs. + // + result = f_open(&File, fqfn, FA_OPEN_EXISTING | FA_READ); - if(osControl.dirMap.file[fileNo] == NULL || osControl.dirMap.file[fileNo]->sdFileName == NULL) + // If no error occurred, read in the header. + // + if(!result) result = f_read(&File, (char *)&dirEnt, TZSVC_CMPHDR_SIZE, &readSize); + + // No errors, read the header. + if(!result && readSize == TZSVC_CMPHDR_SIZE) + { + // Close the file, no longer needed. + f_close(&File); + + // Cache this entry. The SD filename is dynamically allocated as it's size can be upto 255 characters for LFN names. The Sharp name is + // fixed at 17 characters as you cant reliably rely on terminators and the additional data makes it a constant 32 chars long. + osControl.dirMap.mzfFile[fileNo] = (t_sharpToSDMap *)malloc(sizeof(t_sharpToSDMap)); + osControl.dirMap.mzfFile[fileNo]->sdFileName = (uint8_t *)malloc(strlen(fno.fname)+1); + + if(osControl.dirMap.mzfFile[fileNo] == NULL || osControl.dirMap.mzfFile[fileNo]->sdFileName == NULL) + { + printf("Out of memory cacheing directory:%s\n", directory); + for(uint8_t idx=0; idx <= fileNo; idx++) + { + if(osControl.dirMap.mzfFile[idx]) + { + free(osControl.dirMap.mzfFile[idx]->sdFileName); + free(osControl.dirMap.mzfFile[idx]); + osControl.dirMap.mzfFile[idx] = 0; + } + } + result = FR_NOT_ENOUGH_CORE; + } else + { + // Copy in details into this maps node. + strcpy((char *)osControl.dirMap.mzfFile[fileNo]->sdFileName, fno.fname); + memcpy((char *)&osControl.dirMap.mzfFile[fileNo]->mzfHeader, (char *)&dirEnt, TZSVC_CMPHDR_SIZE); + fileNo++; + } + } + } else + { + // Cache this entry. The SD filename is dynamically allocated as it's size can be upto 255 characters for LFN names. The SD service header is based + // on Sharp names which are fixed at 17 characters which shouldnt be a problem, just truncate the name as there is no support for longer names yet! + osControl.dirMap.sdFileName[fileNo] = (uint8_t *)malloc(strlen(fno.fname)+1); + + if(osControl.dirMap.sdFileName[fileNo] == NULL) { printf("Out of memory cacheing directory:%s\n", directory); for(uint8_t idx=0; idx <= fileNo; idx++) { - if(osControl.dirMap.file[idx]) + if(osControl.dirMap.sdFileName[idx]) { - free(osControl.dirMap.file[idx]->sdFileName); - free(osControl.dirMap.file[idx]); - osControl.dirMap.file[idx] = 0; + free(osControl.dirMap.sdFileName[idx]); + osControl.dirMap.sdFileName[idx] = 0; } } result = FR_NOT_ENOUGH_CORE; } else { // Copy in details into this maps node. - strcpy((char *)osControl.dirMap.file[fileNo]->sdFileName, fno.fname); - memcpy((char *)&osControl.dirMap.file[fileNo]->mzfHeader, (char *)&dirEnt, TZSVC_CMPHDR_SIZE); + strcpy((char *)osControl.dirMap.sdFileName[fileNo], fno.fname); +printf("Cacheing:%d,%s,%08lx\n",fileNo, fno.fname, osControl.dirMap.sdFileName[fileNo]); fileNo++; } } } while(!result && fileNo < TZSVC_MAX_DIR_ENTRIES); + } // Success? @@ -3536,6 +3742,8 @@ uint8_t svcCacheDir(const char *directory, uint8_t force) osControl.dirMap.valid = 1; osControl.dirMap.entries = fileNo; strcpy(osControl.dirMap.directory, directory); + // Save the filetype. + osControl.dirMap.type = type; } // Return values: 0 - Success : maps to TZSVC_STATUS_OK @@ -3578,7 +3786,7 @@ printf("FQFN:%s\n", fqfn); // Find the file using the given file number or file name. // - if( (type == MZF && (svcFindFileCache(fqfn, (char *)&svcControl.filename, svcControl.fileNo))) || type == CAS || type == BAS ) + if( (type == MZF && (svcFindFileCache(fqfn, (char *)&svcControl.filename, svcControl.fileNo, type))) || type == CAS || type == BAS ) { // Open the file, fqfn has the FQFN of the correct file on the SD drive. result = f_open(&File, fqfn, FA_OPEN_EXISTING | FA_READ); @@ -3741,7 +3949,7 @@ uint8_t svcLoadFile(enum FILE_TYPE type) { // Find the file using the given file number or file name. // - if(svcFindFileCache(fqfn, (char *)&svcControl.filename, svcControl.fileNo)) + if(svcFindFileCache(fqfn, (char *)&svcControl.filename, svcControl.fileNo, type)) { // Call method to load an MZF file. result = loadMZFZ80Memory(fqfn, 0xFFFFFFFF, 0, 0, 1); @@ -3795,7 +4003,7 @@ uint8_t svcSaveFile(enum FILE_TYPE type) // FRESULT result = FR_OK; char fqfn[FF_LFN_BUF + 13]; // 0:\12345678\ - char asciiFileName[MZF_FILENAME_LEN+1]; + char asciiFileName[TZSVC_FILENAME_SIZE+1]; t_svcDirEnt mzfHeader; // Setup the defaults @@ -3811,7 +4019,7 @@ uint8_t svcSaveFile(enum FILE_TYPE type) // Need to extract and convert the filename to create a file. // - convertSharpFilenameToAscii(asciiFileName, (char *)mzfHeader.fileName, MZF_FILENAME_LEN); + convertSharpFilenameToAscii(asciiFileName, (char *)mzfHeader.fileName, TZSVC_FILENAME_SIZE); // Build filename. // @@ -3856,7 +4064,7 @@ uint8_t svcEraseFile(enum FILE_TYPE type) { // Find the file using the given file number or file name. // - if(svcFindFileCache(fqfn, (char *)&svcControl.filename, svcControl.fileNo)) + if(svcFindFileCache(fqfn, (char *)&svcControl.filename, svcControl.fileNo, type)) { // Call method to load an MZF file. result = f_unlink(fqfn); @@ -4109,12 +4317,12 @@ void processServiceRequest(void) { // Open a directory stream and return the first block. case TZSVC_CMD_READDIR: - status=svcReadDirCache(TZSVC_OPEN); + status=svcReadDirCache(TZSVC_OPEN, svcControl.fileType); break; // Read the next block in the directory stream. case TZSVC_CMD_NEXTDIR: - status=svcReadDirCache(TZSVC_NEXT); + status=svcReadDirCache(TZSVC_NEXT, svcControl.fileType); break; // Open a file stream and return the first block. @@ -4139,7 +4347,7 @@ void processServiceRequest(void) // Close an open dir/file. case TZSVC_CMD_CLOSE: - svcReadDir(TZSVC_CLOSE); + svcReadDir(TZSVC_CLOSE, svcControl.fileType); svcReadFile(TZSVC_CLOSE, svcControl.fileType); svcWriteFile(TZSVC_CLOSE, svcControl.fileType); @@ -4167,7 +4375,7 @@ void processServiceRequest(void) // Change active directory. Do this immediately to validate the directory name given. case TZSVC_CMD_CHANGEDIR: - status=svcCacheDir((const char *)svcControl.directory, 0); + status=svcCacheDir((const char *)svcControl.directory, svcControl.fileType, 0); break; // Load the 40 column version of the SA1510 bios into memory. @@ -4313,7 +4521,7 @@ void processServiceRequest(void) // Need to refresh the directory? Do this at the end of the routine so the Sharp MZ80A isnt held up. if(refreshCacheDir) - svcCacheDir((const char *)svcControl.directory, 1); + svcCacheDir((const char *)svcControl.directory, svcControl.fileType, 1); return; } diff --git a/include/tranzputer.h b/include/tranzputer.h index 190ea83..1473b47 100755 --- a/include/tranzputer.h +++ b/include/tranzputer.h @@ -162,6 +162,8 @@ #define TZSVC_DIRNAME_SIZE 20 // Limit is size of FAT32 directory name. #define TZSVC_WILDCARD_SIZE 20 // Very basic pattern matching so small size. #define TZSVC_FILENAME_SIZE MZF_FILENAME_LEN // Length of a Sharp MZF filename. +#define TZSVC_LONG_FNAME_SIZE (sizeof(t_svcCmpDirEnt) - 1) // Length of a standard filename to fit inside a directory entry. +#define TZSVC_LONG_FMT_FNAME_SIZE 20 // Length of a standard filename formatted in a directory listing. #define TZSVC_SECTOR_SIZE 512 // SD Card sector buffer size. #define TZSVC_STATUS_OK 0x00 // Flag to indicate the K64F processing completed successfully. #define TZSVC_STATUS_FILE_ERROR 0x01 // Flag to indicate a file or directory error. @@ -434,9 +436,11 @@ enum MACHINE_MODE { // Types of file which have handlers and can be processed. // enum FILE_TYPE { - MZF = 0, - CAS = 1, - BAS = 2 + MZF = 0, // Sharp MZF tape image files. + CAS = 1, // BASIC CASsette image files. + BAS = 2, // BASic ASCII text script files. + ALL = 10, // All files to be considered. + ALLFMT = 11 // Special case for directory listings, all files but truncated and formatted. }; // Structure to define a Sharp MZ80A MZF directory structure. This header appears at the beginning of every Sharp MZ80A tape (and more recently archived/emulator) images. @@ -489,8 +493,12 @@ typedef struct { typedef struct __attribute__((__packed__)) { uint8_t valid; // Is this mapping valid? uint8_t entries; // Number of entries in cache. + uint8_t type; // Type of file being cached. char directory[TZSVC_DIRNAME_SIZE]; // Directory this mapping is associated with. - t_sharpToSDMap *file[TZSVC_MAX_DIR_ENTRIES]; // File mapping of SD file to its Sharp MZ80A name. + union { + t_sharpToSDMap *mzfFile[TZSVC_MAX_DIR_ENTRIES]; // File mapping of SD file to its Sharp MZ80A name. + uint8_t *sdFileName[TZSVC_MAX_DIR_ENTRIES]; // No mapping for SD filenames, just the file name. + }; } t_dirMap; @@ -666,11 +674,11 @@ void convertSharpFilenameToAscii(char *, char *, uint8_t); // tranZPUter OS i/f methods. uint8_t setZ80SvcStatus(uint8_t); void svcSetDefaults(enum FILE_TYPE); -uint8_t svcReadDir(uint8_t); -uint8_t svcFindFile(char *, char *, uint8_t); -uint8_t svcReadDirCache(uint8_t); -uint8_t svcFindFileCache(char *, char *, uint8_t); -uint8_t svcCacheDir(const char *, uint8_t); +uint8_t svcReadDir(uint8_t, enum FILE_TYPE); +uint8_t svcFindFile(char *, char *, uint8_t, enum FILE_TYPE); +uint8_t svcReadDirCache(uint8_t, enum FILE_TYPE); +uint8_t svcFindFileCache(char *, char *, uint8_t, enum FILE_TYPE); +uint8_t svcCacheDir(const char *, enum FILE_TYPE, uint8_t); uint8_t svcReadFile(uint8_t, enum FILE_TYPE); uint8_t svcWriteFile(uint8_t, enum FILE_TYPE); uint8_t svcLoadFile(enum FILE_TYPE); diff --git a/libraries/lib/libimath2-k64f.a b/libraries/lib/libimath2-k64f.a index d3f4bdf77e7b9e7c1ad856ee52b69dbceffcb77e..19264f4eee6e9b21b5c86eeab61d92c127c70200 100644 GIT binary patch delta 71 zcmcbScq4Iw44bK;p{1GOM5Q_?Yw|it@r`?D^Fg_r4VESd+cjG1bGh&_BHZ6a2#OxjSw?SRA~OXS0bu(cWe z(SCzd71UzCybfxz7!*=Xp_x*s3M$pP*g=DaysEGzZj7E3TFv^>s!MYz!90s4Z}0ZEpS!%e{ZTn-<|Nx+e1$~;HIx$a2A=gaZ)w{>m}xio{CPrkQIxbePHL( zWQoS+V2RtJr+Ij^H1rQb56iI0JsBFS8!%MNO)(#(9I$Kg(s;~{PLU&+;OmYPu*>TZ Y)9Im)3)tc(`V&#~7E+cKrXDW%10t>BbpQYW delta 759 zcmdmWihb89_6agkW_i;kmlLeS1HoxIHgv1x$d|K>32Tbh+ z`9(1H^aZyVB{omc$l`)ZZZbAQ(kHPw#O4+X-^XnioPS}Bx}C@8^aq1{o@M5^m_^4gV!K zPrS4dMSjyAgnUDe_-5s2=iy!eTDDo>`z)CGn>YMF2iFVq`t~QBjBvlhT(%wPvI3Y6 zpo=88|CM4~iO{x2V*3#lMmtz+fZV)YUZ3$aH#FR~f3RYF1XDi!!8}Is?eAR}*?FMS z5E0=(#(sWSKm&cX{a^wkinq2u%3?(L>w>)G_Rtc>R+zK4Kd5262e$*1K(^m$W1IwY z6U2`0iH!cdFh>F1Aq3+9eVVX6VhzIU+ZSwMjDi`rZ6D(zDBEH>&>pAluZ}a$fr)^< SyZ9pGcc@b=wgYXS#RUMlgW)j% diff --git a/libraries/lib/libummath-k64f.a b/libraries/lib/libummath-k64f.a index 38e756670eb94219f7fde4d0d1a0389099d829d5..4a83f9d6f8a59a9c9c161e3790edc8db2cd201af 100644 GIT binary patch delta 27 dcmaDN@rt`u0>()zbe#Cza#^1b7u8R{Y zx7ki(5{x~0ot(txcZOOp{$@GrTX6P2mtVXvJ^zA?VC>1~Zb@wROW=a5i_1KOBqzDq zzFZI{2XRo$J=GgSmgQordJ*>V2hf vwIFx%olt`E4T17YHs8AVjsv3CaPzradT=>8Yp2aFPiDaRps@P+_BA&E6trsx delta 335 zcmaFznfb|Q<_R)vCI-d^CKel&(;M>xqq^qhUDhzeWh@< rAb0bfP=fRAG?r|>b@3esOz*i{dT=>8Yp2aFPiDaRps@P+_BA&E<4kJ3 diff --git a/libraries/lib/libummisc-k64f.a b/libraries/lib/libummisc-k64f.a index aa5a8bb30a62caf16d1558c5eb3f21ab0f98318c..3963141edf4cdc491c4cb9392a32d7abc3f677da 100644 GIT binary patch delta 39 kcmX?SaL!IYh#5R50tri4$mfT0N-m0&Hw-a delta 39 kcmX?SaL!IYh#5R50tri4$mfT0N#)a#Q*>R diff --git a/libraries/lib/libumstdio-k64f.a b/libraries/lib/libumstdio-k64f.a index ed1bdfd738b6856fc58be12efacfe56ee4f6b3ec..3e82d1836b96f3c20506239676b404320c43401f 100644 GIT binary patch delta 371 zcmdn=k!90ImI*R!riO-=W`-M;N*JNc$sd9xHg93{;zjVqH%s#$=0Wf!Hvf@ULy{NU zY^V7`8X+&f+1YhDAC$lOLoljZqeKgswVMlS=W!$J)9y@1vL|Y?oebONA5)JZiHUE% zy=XfMfBpL7NNy3|JbCYFxO_pa#O9h)lThurrVf|?5G=kq|4}iD{{QcVQRMai1S9je k&*xx7C@82E-+o?%QJD+L7u)&e8OxEhNNiuC&B(_K0NQVOJOBUy delta 371 zcmdn=k!90ImI*R!CI-d^CYBqON*Ezbi^(5?B{pwi^x{SE#WzdyALc>uB{u(&Rzs2( z+ia)#LK-12zS-GzIUkh2`9mXOYOxx tBCr1^7@5C)J_jR0K|!tf_VXf)%3Kg%fKAxWFV9$xq(x%;5^Y94UI3UOcj*8C diff --git a/zOS/Makefile.k64f b/zOS/Makefile.k64f index ce904ab..7dcb167 100644 --- a/zOS/Makefile.k64f +++ b/zOS/Makefile.k64f @@ -48,7 +48,7 @@ TARGET = main TEENSY = 35 # Set to 24000000, 48000000, or 96000000 to set CPU core speed -TEENSY_CORE_SPEED = 120000000 +TEENSY_CORE_SPEED = 168000000 # Some libraries will require this to be defined # If you define this, you will break the default main.cpp diff --git a/zOS/src/zOS.cpp b/zOS/src/zOS.cpp index 62d1e01..07560d8 100644 --- a/zOS/src/zOS.cpp +++ b/zOS/src/zOS.cpp @@ -343,8 +343,8 @@ int cmdProcessor(void) // Setup memory on Z80 to default. loadTranZPUterDefaultROMS(); - // Cache initial directory. - svcCacheDir(TZSVC_DEFAULT_MZF_DIR, 1); + // Cache initial director. + svcCacheDir(TZSVC_DEFAULT_MZF_DIR, MZF, 1); // For the tranZPUter, once we know that an SD card is available, launch seperate thread to handle hardware and service functionality. // No SD card = no tranZPUter functionality.