/**************************************************************** * zx81load.c * ZX81-Programme wie vom Band abspielen * ===================================== * * 02.05.99 Bodo Wenzel V1.0, quick-and-dirty * 2002-04-28 Bodo Wenzel V1.1, auch Linux-Version, keine * Atari-Version mehr * 2002-05-06 Bodo Wenzel V1.2, echte Maschinen brauchen * doch gepulste Signale ****************************************************************/ #include #include #include #if defined(__TOS__) #error "Sorry, Atari-Version nicht weitergepflegt." #include #elif defined(__MSDOS__) #include #elif defined(__unix__) #include #include #include #else #error "Anpassungen noetig!" #endif void quit(char *msg, int ret) { /*-------------------------*/ puts(msg); exit(ret); } /* Das Verfahren ist bei allen Betriebssystemen gleich: Die * Schnittstelle wird auf 4800-8N1 eingestellt. Da das ZX81-BASIC die * Bits "nur" ueber die Summe der zeitlichen Laenge der Pulse * identifiziert, reicht es, entsprechende Bytes zu senden. */ #if defined(__TOS__) int serinit(void) { /*-------------*/ Rsconf(2, 0, 0x88, 0x01, 0x05, 0); return 1; } void txdbyte(int d) { /*---------------*/ int i; for (i = 0; i < 8; i++, d <<= 1) { if ((d & 0x80) != 0) Bconout(1, 0x55); Bconout(1, 0xF5); } } #endif #if defined(__MSDOS__) int com; int serinit(char *par) { /*------------------*/ com = -1; if (*par == '\0') com = 1; else if (sscanf(par, "%d", &com) != 1) return 0; if (com < 1 || com > 4) return 0; com--; bioscom(0, 0xC3, com); if ((bioscom(3, 0, com) & 0x6000) != 0) return 1; return 0; } void txdbyte(int d) { /*---------------*/ int i; for (i = 0; i < 8; i++, d <<= 1) { if ((d & 0x80) != 0) bioscom(1, 0x55, com); bioscom(1, 0xF5, com); } } #endif #if defined(__unix__) int fd; struct termios old_attr; void serexit(void) { /*--------------*/ tcsetattr(fd, TCSADRAIN, &old_attr); close(fd); } int serinit(char *port) { /*-------------------*/ struct termios attr; fd = open(port, O_RDWR | O_NOCTTY); if (fd < 0) return 0; tcgetattr(fd, &attr); old_attr = attr; atexit(serexit); cfmakeraw(&attr); cfsetospeed(&attr, B4800); cfsetispeed(&attr, B4800); if (tcsetattr(fd, TCSANOW, &attr) != 0) return 0; tcflush(fd, TCIOFLUSH); return 1; } void txdbyte(int d) { /*---------------*/ int i, c; tcflush(fd, TCIFLUSH); for (i = 0; i < 8; i++, d <<= 1) { if ((d & 0x80) != 0) { c = 0x55; (void)write(fd, &c, 1); } c = 0xF5; (void)write(fd, &c, 1); } } #endif int convert(int c) { /*--------------*/ if (c >= '0' && c <= '9') return c - '0' + 0x1C; if (c >= 'a' && c <= 'z') return c - 'a' + 0x26; if (c >= 'A' && c <= 'Z') return c - 'A' + 0x26; switch (c) { case '"': return 0x0B; case '$': return 0x0D; case ':': return 0x0E; case '?': return 0x0F; case '(': return 0x10; case ')': return 0x11; case '>': return 0x12; case '<': return 0x13; case '=': return 0x14; case '+': return 0x15; case '-': return 0x16; case '*': return 0x17; case '/': return 0x18; case ';': return 0x19; case ',': return 0x1A; case '.': return 0x1B; default: break; } return 0x08; } typedef unsigned char uchar; #define START (0x4009) #define E_LINE (0x4014) #define BUFLEN (0xC000L - START) uchar *buffer; int main(int argc, char *argv[]) { /*----------------------------*/ FILE *f; long e_line, d, l, i, dd; char *s1,*s2; #if defined(__TOS__) if (argc < 2) quit("Aufruf: ZX81LOAD ", 1); #endif #if defined(__MSDOS__) if (argc < 2) quit("Aufruf: ZX81LOAD []", 1); #endif #if defined(__unix__) setbuf(stdout, NULL); if (argc < 3) quit("Aufruf: zx81load ", 1); #endif if ((buffer = (uchar *)malloc((size_t)BUFLEN)) == NULL) quit("Speicherueberlauf", 4); #if defined(__TOS__) if (!serinit()) quit("Kann Schnittstelle nicht initialisieren!", 3); #endif #if defined(__MSDOS__) if (!serinit(argc >= 3 ? argv[2] : "")) quit("Kann Schnittstelle nicht initialisieren!", 3); #endif #if defined(__unix__) if (!serinit(argv[2])) quit("Kann Schnittstelle nicht initialisieren!", 3); #endif if ((f = fopen(argv[1], "rb")) == NULL) quit("Kann Datei nicht oeffnen!", 2); fseek(f, E_LINE-START, SEEK_SET); if ((d = fgetc(f)) != EOF) { e_line = d; if ((d = fgetc(f)) != EOF) { e_line |= d << 8; fseek(f, 0, SEEK_END); l = ftell(f); d = EOF; if (e_line > START && e_line - 1 <= START + l) { l = e_line - START; fseek(f, l - 1, SEEK_SET); d = fgetc(f); } } } if (d != 0x80) quit("Kein ZX81-Programm!", 2); fseek(f, 0, SEEK_SET); if (fread(buffer, sizeof(uchar), (size_t)l, f) != l) quit("Lesefehler mit Datei!", 2); fclose(f); if ((s1 = strrchr(argv[1], '\\')) == NULL) if ((s1 = strrchr(argv[1], '/')) == NULL) s1 = argv[1] - 1; s1++; if ((s2 = strrchr(s1, '.')) != NULL) *s2 = '\0'; printf("\"%s\" %ld Bytes:\n", s1, l); dd = l >> 6; for (d = 0; d < l; d += dd) putchar('-'); putchar('\r'); while (s1[1] != '\0') txdbyte(convert(*s1++)); txdbyte(convert(*s1) | 0x80); for (d = 0, i = 0; i < l; i++) { if (i > d) { d += dd; putchar('*'); } txdbyte(buffer[(size_t)i]); } putchar('\n'); return 0; } /* === Ende =================================================== */