/* ** a1kb.c: APPLE I Keyboard Emulator via PC LPT port */ #include #include #include #define LINUX 1 #ifdef LINUX #include #include #include #include #include #else #include #endif #undef DEBUG /* turn on to get more verbose and detailed output */ /* Width of STROBE pulse. On the Aero 4/33C, 0.1 sec for 7700 ticks */ #define DELAY 7700 #define BACKSP 0x5f #define POS1 0x02 typedef unsigned char byte; typedef unsigned int word; word lpt_ad = 0x378; #ifdef LINUX int _getch() { struct termios oldt, newt; int ch; tcgetattr(STDIN_FILENO, &oldt); newt = oldt; newt.c_lflag &= ~(ICANON | ECHO); tcsetattr(STDIN_FILENO, TCSANOW, &newt); ch = getchar(); tcsetattr(STDIN_FILENO, TCSANOW, &oldt); return ch; } int _kbhit() { struct termios oldt; tcgetattr(0, &oldt); struct termios newt = oldt; newt.c_lflag &= ~ICANON; tcsetattr(0, TCSANOW, &newt); int byteswaiting; ioctl(0, FIONREAD, &byteswaiting); tcsetattr(0, TCSANOW, &oldt); return byteswaiting > 0; } int RD_PORT() { int ch; /* Get access to the ports */ if (ioperm(lpt_ad, 3, 1)) { perror("ioperm"); exit(1); } ch = inb(lpt_ad); /* We don't need the ports anymore */ if (ioperm(lpt_ad, 3, 0)) { perror("ioperm"); exit(1); } return ch; } int WR_DPORT (int x) { /* Get access to the ports */ if (ioperm(lpt_ad, 3, 1)) { perror("ioperm"); exit(1); } outb(x, lpt_ad); /* We don't need the ports anymore */ if (ioperm(lpt_ad, 3, 0)) { perror("ioperm"); exit(1); } } int WR_CPORT (int x) { /* Get access to the ports */ if (ioperm(lpt_ad, 3, 1)) { perror("ioperm"); exit(1); } outb(x, lpt_ad + 2); /* We don't need the ports anymore */ if (ioperm(lpt_ad, 3, 0)) { perror("ioperm"); exit(1); } } #else #define RD_DPORT() _inp(lpt_ad) #define WR_DPORT(x) _outp(lpt_ad, x) #define WR_CPORT(x) _outp(lpt_ad + 2, x) #endif void do_cport(int idle, int active) { unsigned long i; WR_CPORT(idle); for(i = 0; i < DELAY * 8l; i++) WR_CPORT(active); WR_CPORT(idle); } #ifdef LINUX #define FILENAMLEN 16 #else #define FILENAMLEN 128 #endif int main(int argc, char *argv[]) { int i, j, key, zflg; FILE *fp; char fname[FILENAMLEN + 1]; WR_CPORT(0x0c); zflg = 0; fp = (FILE *) 0; while(1) { if(fp) { /* if file is open, get characters from file, not from keyboard */ key = fgetc(fp); if((key == EOF) || _kbhit()) { fclose(fp); fp = (FILE *) 0; continue; } /* process special characters here, may end with continue */ if(key == 0x0a) key = 0x0d; /* convert LF to CR */ } else key = _getch(); /* no file open, get characters from keyboard */ if(key) { /* if key code != 0, emulate key press */ if(zflg) { /* this code had a preceeding zero key code */ zflg = 0; if(key == 0x3b) { #ifdef DEBUG printf("\nF1: RESET\n"); #endif do_cport(0x0c, 0x08); continue; } else if(key == 0x3c) { #ifdef DEBUG printf("\nF2: CLR SCREEN\n"); #endif do_cport(0x0c, 0x04); continue; } else if(key == 0x3d) { if(fp) fclose(fp); do { printf("\nEnter filename: "); if(!fgets(fname, FILENAMLEN, stdin)) continue; j = strlen(fname); if(fname[j - 1] == '\n') fname[--j] = '\0'; } while(!j); fp = fopen(fname, "r"); if(fp == NULL) printf("Sorry, can't open file '%s'", fname); putchar('\n'); continue; } else if(key == 0x53) key = BACKSP; else if(key == 0x4b) key = POS1; } /* end of key codes with preceeding zero key code */ #ifdef DEBUG printf(" %.2x", key); #endif if(islower(key)) key = toupper(key); key &= 0x7f; #ifndef DEBUG putchar(key); if(key == 0x0d) putchar('\n'); #endif WR_DPORT(key); key |= 0x80; for(i = 0; i < DELAY; i++) WR_DPORT(key); key &= 0x7f; for(j = 0; j < 10; j++) { for(i = 0; i < DELAY; i++) WR_DPORT(key); if(fp == NULL) break; } } else zflg = 1; /* if key code == 0, memorize this. */ } exit(0); } /* FIN a1kb.c --------------------------------------------------------------- */