/* tapls - List for Spectrum TAP files Copyright (C) 2023 Ian Cowburn This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include #include /* ---------------------------------------- MACROS */ #ifndef TRUE #define TRUE 1 #endif #ifndef FALSE #define FALSE 0 #endif /* ---------------------------------------- TYPES */ typedef unsigned char Z80Byte; typedef unsigned short Z80Word; /* ---------------------------------------- PRIVATE DATA */ const char *name; /* ---------------------------------------- PRIVATE FUNCTIONS */ static Z80Byte GetTAPByte(FILE **tapfile) { int ret=0; if (*tapfile) { ret = fgetc(*tapfile); if (ret == EOF) { ret = 0; fclose(*tapfile); *tapfile = NULL; } } return (Z80Byte)ret; } static Z80Word GetTAPLSBWord(FILE **tapfile) { int c1,c2; c1 = GetTAPByte(tapfile); c2 = GetTAPByte(tapfile); return (Z80Word)(c1+(c2<<8)); } static void TAPLoad(const char *path, FILE **tapfile, int dump) { while(TRUE) { Z80Word blen; Z80Byte type,b,csum,tape_csum; int warned = FALSE; int col = 0; char asc[17] = {0}; unsigned off = 0; b = 0; blen = GetTAPLSBWord(tapfile); type = GetTAPByte(tapfile); if (!*tapfile) { return; } csum = type; printf("%s: type = %u, block len = %u\n", path, (unsigned)type, (unsigned)blen); /* Knock of block type */ blen--; while(blen) { b = GetTAPByte(tapfile); if (!*tapfile && !warned) { fprintf(stderr,"%s: hit EOF during block (%u left)\n", path, blen); warned = TRUE; } if (blen > 1) { csum ^= b; } if (dump) { if (col == 0) { printf("%4.4x:", off); off += 16; } printf(" %2.2x", (unsigned)b); asc[col++] = isprint(b) ? b : '.'; if (col == 16) { printf(" %s\n", asc); memset(asc, 0, sizeof asc); col = 0; } } blen--; } if (dump && col > 0) { while(col++ < 16) { printf(" **"); } printf(" %s\n", asc); } tape_csum = b; /* Check the checksum */ printf("%s: checksums %u (calc) %u (tape) %s\n", path, (unsigned)csum, (unsigned)tape_csum, csum == tape_csum ? "match":"don't match"); } } static void TapLS(const char *path, int dump) { FILE *fp; fp = fopen(path, "rb"); if (fp) { TAPLoad(path, &fp, dump); } else { fprintf(stderr, "%s: failed to open '%s'\n", name, path); } } static void Usage(void) { fprintf(stderr, "%s: usage %s [-d] [-h] tapefile ...\n", name, name); } /* ---------------------------------------- MAIN */ int main(int argc, char *argv[]) { int file_i; int f; int dump = FALSE; if (strrchr(argv[0], '/')) { name = strrchr(argv[0], '/') + 1; } else { name = argv[0]; } file_i = 1; while(file_i < argc && argv[file_i][0] == '-') { switch(argv[file_i][1]) { case 'd': dump = TRUE; break; case 'h': Usage(); return EXIT_SUCCESS; default: fprintf(stderr, "%s: unknown switch '%c'\n", name, argv[file_i][1]); Usage(); return EXIT_FAILURE; } file_i++; } if (file_i == argc) { Usage(); return EXIT_FAILURE; } for(f = file_i; f < argc; f++) { TapLS(argv[f], dump); } return EXIT_SUCCESS; } /* END OF FILE */