// T64TOP00.CPP (Visual C++ 1.00) -- T64-Dateien in das PC64-Format umwandeln #include #include #include #include #include #include #include #include #include #include #include typedef unsigned char byte; typedef unsigned short word; typedef unsigned int uint; typedef unsigned long dword; typedef enum { FALSE, TRUE } flag; struct { char acTag[8]; char acName[17]; byte bRecord; } C64Header; struct T64EntryStruct { byte bType; byte bSecAdr; word wStartAdr; word wEndAdr; word wReserved; long lOffset; long lReserved; char acName[17]; } T64Entry; struct { char acTag[32]; word wVersion; word wEntries; word wUsedEntries; word wReserved; char acName[24]; T64EntryStruct Dummy; } T64Header; byte abUnfixed[96] = { 0x43,0x36,0x34,0x53,0x20,0x74,0x61,0x70,0x65,0x20,0x66,0x69,0x6C,0x65,0x0D,0x0A, 0x44,0x65,0x6D,0x6F,0x20,0x74,0x61,0x70,0x65,0x1A,0x2E,0x2E,0x2E,0x2E,0x2E,0x2E, 0x00,0x01,0x1E,0x00,0x00,0x00,0x00,0x00,0x44,0x45,0x4D,0x4F,0x20,0x54,0x41,0x50, 0x45,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20, 0x01,0x44,0x01,0x08,0xC6,0xC3,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00, 0x46,0x49,0x4C,0x45,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20 }; // Auf groágeschriebenen Vokal prfen static inline flag isvocal(char c) { return (flag)(memchr("AEIOU", c, 5) != NULL); } // Dateinamen von 16 Zeichen auf 8 Zeichen reduzieren flag ReduceName(const char* sC64Name, char* pDosName) { int iStart; // L„nge berprfen int iLen = strlen(sC64Name); if (iLen > 16) { return FALSE; } // Bei einem Jokerzeichen alle Dateien durchsuchen if (strpbrk(sC64Name, "*?")) { strcpy(pDosName, "*"); return TRUE; } // In Puffer umkopieren char sBuf[16 + 1]; memset(sBuf, 0, 16); strcpy(sBuf, sC64Name); // Gltige Zeichen holen for (int i = 0; i <= 15; i++) { switch (sBuf[i]) { case ' ': case '-': // Leerzeichen durch Unterstrich ersetzen sBuf[i] = '_'; break; default: // Kleinbuchstaben groá machen if (islower((byte)sBuf[i])) { sBuf[i] -= 32; break; } // Groábuchstaben und Ziffern sind OK if (isalnum((byte)sBuf[i])) { break; } // Ungltige Zeichen entfernen if (sBuf[i]) { sBuf[i] = 0; iLen--; } } } // Namen auf 8 Zeichen bringen if (iLen <= 8) { goto Copy; } // Unterstriche entfernen for (i = 15; i >= 0; i--) { if (sBuf[i] == '_') { sBuf[i] = 0; if (--iLen <= 8) { goto Copy; } } } // Ersten Nicht-Vokal suchen for (iStart = 0; iStart < 15; iStart++) { if (sBuf[iStart] && !isvocal(sBuf[iStart])) { break; } } // Vokale entfernen for (i = 15; i >= iStart; i--) { if (isvocal(sBuf[i])) { sBuf[i] = 0; if (--iLen <= 8) { goto Copy; } } } // Konsonanten entfernen for (i = 15; i >= 0; i--) { if (isalpha(sBuf[i])) { sBuf[i] = 0; if (--iLen <= 8) { goto Copy; } } } // šbriggebliebene Ziffern entfernen for (i = 0; i <= 15; i++) { if (sBuf[i]) { sBuf[i] = 0; if (--iLen <= 8) { goto Copy; } } } Copy: // Dummy-Namen bei L„nge = 0 erfinden if (!iLen) { strcpy(pDosName, "_"); return TRUE; } // Dateinamen umkopieren char* p = pDosName; for (i = 0; i <= 15; i++) { if (sBuf[i]) { *p++ = sBuf[i]; } } *p = 0; // Dos-Namen auf Ger„t prfen int hFile = _open(pDosName, _O_BINARY | _O_RDONLY); if (hFile == -1) { return TRUE; } // Wenn es ein Ger„tename ist, dann '_' als letztes Zeichen anh„ngen if (isatty(hFile)) { if (iLen < 8) { strcat(pDosName, "_"); } else if (pDosName[7] != '_') { pDosName[7] = '_'; } else { pDosName[7] = 'X'; } } // Zur Probe ge”ffnetes Ger„t wird nicht mehr gebraucht _close(hFile); return TRUE; } void CopyFile(int hSource, char* pcDosPath, char* pcDosName) { int i; char* pcNum; int hFile; printf(" %-18s", T64Entry.acName); if (T64Entry.bType != 1) { printf("(Memory Snapshot)\n"); return; } ReduceName(T64Entry.acName, pcDosName); strcat(pcDosName, ".P*"); _find_t find; uint uFind = _dos_findfirst(pcDosPath, _A_NORMAL, &find); while (!uFind) { strcpy(pcDosName, find.name); hFile = _open(pcDosPath, _O_BINARY | _O_RDONLY); if (hFile == -1) { goto Error; } if (_read(hFile, &C64Header, 26) == 26 && !strcmp(C64Header.acTag, "C64File")) { if (!strcmp(C64Header.acName, T64Entry.acName)) { if (_close(hFile) == -1) { goto Error; } goto Found; } } if (_close(hFile) == -1) { goto Error; } uFind = _dos_findnext(&find); } if (uFind != 0x12) { goto Error; } pcNum = strchr(pcDosName, '.') + 2; for (i = 0; i < 100; i++) { sprintf(pcNum, "%02d", i); if (_access(pcDosPath, 0)) { goto Found; } } #if GERMAN printf("Keine Ziffern fr Erweiterung mehr frei\n"); #else printf("No more numbers available\n"); #endif return; Found: printf("ÄÄ> %s ", pcDosName); hFile = _open(pcDosPath, _O_BINARY | _O_RDWR | _O_CREAT | _O_TRUNC, _S_IREAD | _S_IWRITE); if (hFile == -1) { goto Error; } memset(&C64Header, 0, 26); strcpy(C64Header.acTag, "C64File"); strcpy(C64Header.acName, T64Entry.acName); errno = ENOSPC; if (_write(hFile, &C64Header, 26) != 26) { goto Error; } if (_write(hFile, &T64Entry.wStartAdr, 2) != 2) { goto Error; } { _lseek(hSource, T64Entry.lOffset, SEEK_SET); static byte abBuffer[16384]; long lSize = T64Entry.wEndAdr - T64Entry.wStartAdr; while (lSize > 0) { int iBytes; if (lSize > 16384) { iBytes = 16384; } else { iBytes = (int)lSize; } int iError = _read(hSource, abBuffer, iBytes); if (iError == -1) { goto Error; } if (_write(hFile, abBuffer, iError) != iError) { goto Error; } if (iError != iBytes) { if (_close(hFile) == -1) { goto Error; } #if GERMAN fprintf(stderr, "Lesen ber das Dateiende hinaus!\n"); #else fprintf(stderr, "End of file encountered!\n"); #endif return; } lSize -= iBytes; } } if (_close(hFile) == -1) { goto Error; } printf("\n"); return; Error: perror(NULL); exit(1); } void Convert(char acName[80]) { char* pcName = strrchr(acName, '\\'); if (pcName == NULL) { pcName = acName; } else { pcName++; } int hFile = _open(acName, _O_BINARY | _O_RDONLY); if (hFile != -1) { if (_read(hFile, &T64Header, 96) == 96 && strstr(T64Header.acTag, "C64") && strstr(T64Header.acTag, "tape")) { T64Entry.wStartAdr = T64Header.Dummy.wStartAdr; T64Header.Dummy.wStartAdr = 0x0801; if (!memcmp(&T64Header, abUnfixed, 96)) { #if GERMAN printf("%s (fr C64S ist FIXTAPE.EXE n”tig)\n", acName); #else printf("%s (use FIXTAPE.EXE for C64S)\n", acName); #endif T64Entry.bType = 1; T64Entry.bSecAdr = 1; T64Entry.wEndAdr = T64Entry.wStartAdr + (word)(_filelength(hFile)) - 1024; T64Entry.lOffset = 1024; memset(T64Entry.acName, 0, 16); memcpy(T64Entry.acName, pcName, strlen(pcName) - 4); CopyFile(hFile, acName, pcName); } else { printf("%s\n", acName); for (word wEntry = 0; wEntry < T64Header.wEntries; wEntry++) { _lseek(hFile, 64 + wEntry * 32, SEEK_SET); if (_read(hFile, &T64Entry, 32) != 32) { #if GERMAN fprintf(stderr, "Lesen ber das Dateiende hinaus!\n"); #else fprintf(stderr, "End of file encountered!\n"); #endif goto NextFile; } if (T64Entry.bType) { int i = 15; while (i && T64Entry.acName[i] == ' ') { T64Entry.acName[i--] = 0; } if (!strcmp(T64Entry.acName, "FILE")) { memset(T64Entry.acName, 0, 16); memcpy(T64Entry.acName, pcName, strlen(pcName) - 4); } CopyFile(hFile, acName, pcName); } } } } NextFile: if (_close(hFile) != -1) { return; } } perror(NULL); exit(1); } void ConvertDir(char* pcDir) { printf("%-79s\r", pcDir); char acName[80]; strcpy(acName, pcDir); char* pcName = acName + strlen(acName); if (pcName[-1] != '\\') { *pcName++ = '\\'; } strcpy(pcName, "*.*"); _find_t find; uint uFind = _dos_findfirst(acName, _A_NORMAL | _A_SUBDIR, &find); while (!uFind) { strcpy(pcName, find.name); if (find.attrib & _A_SUBDIR) { if (find.name[0] != '.') { ConvertDir(acName); } } else { char* pcExt = strchr(pcName, '.'); if (pcExt && strcmpi(pcExt, ".T64") == 0) { Convert(acName); } } uFind = _dos_findnext(&find); } if (uFind == 0x12) { return; } perror(NULL); exit(1); } int main(int argc, char** argv) { #ifdef _DEBUG _bdos(0x0D, 0, 0); #endif #if GERMAN printf("T64-Dateien des C64S in das PC64-Format umwandeln\n"); #else printf("Converting T64 files from C64S into the PC64 format\n"); #endif char acDir[80]; if (argc < 2) { _fullpath(acDir, ".", 80); } else { _fullpath(acDir, argv[1], 80); _strupr(acDir); } int hTest = _open(acDir, _O_BINARY | _O_RDONLY); if (hTest != -1) { _close(hTest); Convert(acDir); return 0; } char* pcExt = strchr(acDir, '.'); if (pcExt == 0) { pcExt = acDir + strlen(acDir); strcpy(pcExt, ".T64"); hTest = _open(acDir, _O_BINARY | _O_RDONLY); if (hTest != -1) { _close(hTest); Convert(acDir); return 0; } *pcExt = 0; } #if GERMAN printf("Startverzeichnis ist %s\n", acDir); #else printf("Start directory is %s\n", acDir); #endif ConvertDir(acDir); printf("\r%80c", '\r'); return 0; }