Further updates for the MZ-700 mode and NASCOM basic

This commit is contained in:
Philip Smart
2020-06-19 01:14:08 +01:00
parent 64ebf13d14
commit 3f250cab48
10 changed files with 351 additions and 135 deletions

View File

@@ -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\<filename>
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;
}

View File

@@ -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);

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -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

View File

@@ -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.