From 3effdc677301f7183c963e6d6d701e3f15107e13 Mon Sep 17 00:00:00 2001 From: dschmenk Date: Sat, 24 Aug 2013 21:52:44 -0700 Subject: [PATCH] Use Apple II I/O vectors for hooking in client functionality Can now have an Apple II console from Linux! --- src/A2PI.PO | Bin 143360 -> 143360 bytes src/Makefile | 2 +- src/a2pid.c | 49 +++++++++++++++++++++++++----- src/a2term.c | 83 +++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 126 insertions(+), 8 deletions(-) create mode 100755 src/a2term.c diff --git a/src/A2PI.PO b/src/A2PI.PO index 4bc246bb2b312c81cefd61805f92c7da25f25b55..26ec2e3124b9c5dff71e62fb7bff01ef2664f5e4 100755 GIT binary patch delta 2257 zcmZ`*eN0nV6n~}ARs~Z;#i4P}sZqB6!H45x?w@_&Sk`@^OZZFKvTT|dqua8%L~R8N zh+O=58}z!w-Bn0>mHZsf|nSFuFm@O>~h~cO(N&+JiIp5mXi^xD&AOrp& z7!e5tC#dx@BEQ9=Bq{{P{lQ?Ai^N}A6AJo?Bu7K4D<*`4{y>2I!U}<*2)A@@<%?8c z$Nix(L5&mhj|&r2oFr77L_`Wnh(zTWS2lagwWHn^h+Pj6VRVeNdV3KlLz;3K4L|l= zp-RHjhoa%2wx&m*istDVM3FIhTnNY>HOPR_DSG57OSrZ;m+PPK_)X-vKZo5F`x_K(KU1r!tHp-5yn1_|<$^H&2DAR-cz{X{#Y zs?a3SECR^)KcJ4TBy327U4;@q4pkVC#juK@Sxts|5^tsIBp@&vAdjP8Lxv6cVs3z3$$!S>#V`j60*Os z26OE*Yu22`*Un(Xq~2|SjZS0!5!?RI&Geh~)+)?R&8)J$j`DntBEALX`y9o5B`WYa zNJqx<@|+t9q;ZSF_)*!AeFmGPA~p2ED7 zEpzUMAN+Nm!h6j=Q)Sah44&!tq?GCR0Y6fYrFY5kE>o^4uD9Ck&hT+8-3m8g=_b)P zHej+G?&KMTYxW&XMGoBeAQjbOvI4Ab2hOO)(r(3P%(aiy;dr}slkktvJt8Tm+`#d`rQWm#I)-$uG@gUNxmLjj)2*&guSIY2ImC&NLR5 zY{|=GJ~gdn?A}bnIT#Cn&fAp1Dolt9-~A-PIkgp@(fA2aqD3`WLZy>a?M7|hJr4Gt z&bI+I>2gnEF;$*!el^tjR+xKAe`<|QTQxZc)b6?xg!vzcve3b-GUe1Be)ix;F|T~r zqU-+qNQxeMj5`|t*fpQBwG^m?Fr^f_coG9yHdpb-pkz>F`mUvKYex&J!+b4>P*8WB zVykN5uHM^dv*UP9t+AYTR+qtHxM;_n)p)n*AbS{ZUR706Me4guqFvHkuQiLOq$RG? z>;os8g{>AWo{`dBoT^q@w_))+X|?NnsvpLcrgHuqY)3gvf7YrNv02J-wSZf3v>E7O z%AB^up)1SzA2qOwSN-(8-RUq;7E;03U{wTk05DyOoLQ%Ei$>I*czX!rZ7ngHqL)H_;S4KUx|N8q{uIKLaTuDXGYQ;~2 d*NF!yWhcP_O`P;jSLEnw;tQAK3%Y%U{{YRcG8O;; delta 943 zcmZ8dU1$_n6uz^wJ2TC0>C7>9w^rI|M9dZowS-o&LepxAFh!e02neEmQjlVQ(Db2k zTU|**Zhvyyhft{FU?5|&VV4OMt%2EOcg>jH$xU{H4OrMBUBgz|wF%ZHg1xiJQxA8} z`M&d=bI+L@D@(Dml;i^bAd)wbKwxY0Z6ES%3%Y}35BN~HqqDWW^Uy($dG_cu;?Rp$ zdthAPp0eanZ68_qcPBAd#;l&zM$YK$eW8^7rBs}pbM@@(ynZ=3mQ3QwnfcNh&1JF~ za_zR^OC`yXUyXtCV8i>TKKSsXkI!^}61BL72b?un{@qV@Rl?*_Wlu!UXVQAwU6{@; zV7*vM>kP0^BKFLhrOrV?eP)cxiP#6+f zX+7&eTr%zW6BThtbf)N!T_ZQ4wq1WlEh{>h91EnU8s5NIxXwl#ph5jqzXN2rx_NUE z#!G;af3c4ZDuVe~9e$KRw#;ki6;iH7&LaFbZ_0Ry-#>(x`Gjm^7nm=&K;O~7NJ&wt z#%mn7Ge8$z3iOW7_fyat+2G_Yw#(ISKc0rG5B)d~`bL&bOv96Tpl{VRF&Zlrpf;)v zD_3O6jIrsXvi+qC=I3foQLiie`dBP~PjTWsTkd6p6H7eXgZ&!P%8GfOsq8|}=RL2z ztKb5d7Z_yCi9$UWQpoNHTU&Eb+jK!}^PV~-#D&ouj7-6Csau_d=E%{V5vc)PyW89n z-QD!2cA#~y+WN}D{Y|JzYDE1lFYkI4HCspS861fPUbmjR-{a#a(iw7b=@_}v9wCu- zjXdA+8yV~fTET}dXDs{99@TqOk`tr6HZD6~)1dKs2({uLfPxdPJMvG;y_W1t; DBM6_L diff --git a/src/Makefile b/src/Makefile index 2701e0b..c18eaf4 100755 --- a/src/Makefile +++ b/src/Makefile @@ -1,4 +1,4 @@ -BIN=a2serclk a2pid a2mon dskread dskwrite bintomon bload brun +BIN=a2serclk a2pid a2mon a2term dskread dskwrite bintomon bload brun all: $(BIN) diff --git a/src/a2pid.c b/src/a2pid.c index 5b597d2..7f1ebc3 100755 --- a/src/a2pid.c +++ b/src/a2pid.c @@ -453,7 +453,7 @@ void prlog(char *str) } struct a2request *addreq(int a2fd, int reqfd, int type, int addr, int count, char *buffer) { - char rwchar; + char rwchar; struct a2request *a2req = a2reqfree; if (a2req == NULL) a2req = malloc(sizeof(struct a2request)); @@ -557,8 +557,8 @@ void main(int argc, char **argv) struct uinput_user_dev uidev; struct termios oldtio,newtio; unsigned char iopkt[16]; - int i, c, lastbtn; - int a2fd, kbdfd, moufd, srvfd, reqfd, maxfd; + int i, c, lastbtn, cout; + int a2fd, kbdfd, moufd, srvfd, reqfd, coutfd, maxfd; struct sockaddr_in servaddr; fd_set readset, openset; char *devtty = "/dev/ttyAMA0"; /* default for Raspberry Pi */ @@ -737,7 +737,8 @@ void main(int argc, char **argv) */ reset: state = RUN; - reqfd = 0; + cout = -1; + reqfd = coutfd = 0; FD_ZERO(&openset); FD_SET(a2fd, &openset); FD_SET(srvfd, &openset); @@ -758,7 +759,7 @@ reset: { if (read(a2fd, iopkt, 3) == 3) { - // printf("a2pi: Event [0x%02X] [0x%02X] [0x%02X]\n", iopkt[0], iopkt[1], iopkt[2]); + //printf("a2pi: Event [0x%02X] [0x%02X] [0x%02X]\n", iopkt[0], iopkt[1], iopkt[2]); switch (iopkt[0]) { case 0x80: /* sync */ @@ -850,6 +851,26 @@ reset: else state = RESET; break; + case 0x96: /* send input char to Apple II */ + if (a2reqlist) /* better have an outstanding request */ + { + //printf("a2pid: call address 0x%04X\n", a2reqlist->addr); + newtio.c_cc[VMIN] = 1; /* blocking read until 1 char received */ + tcsetattr(a2fd, TCSANOW, &newtio); + if (!writeword(a2fd, a2reqlist->addr, 0x97)) + state = RESET; + newtio.c_cc[VMIN] = 3; /* blocking read until 3 chars received */ + tcsetattr(a2fd, TCSANOW, &newtio); + } + else + state = RESET; + break; + case 0x98: /* get output char from Apple II */ + if (coutfd) + write(coutfd, iopkt, 2); + else + cout = iopkt[1]; + break; case 0x9E: /* request complete ok */ case 0x9F: /* request complete error */ if (a2reqlist) /* better have an outstanding request */ @@ -951,11 +972,25 @@ reset: addreq(a2fd, reqfd, 0x94, addr, 0, NULL); } break; + case 0x96: /* send input char to Apple II */ + if (read(reqfd, iopkt, 1) == 1) + addreq(a2fd, reqfd, 0x96, iopkt[0], 0, NULL); + break; + case 0x98: /* get output chars from Apple II */ + if (cout >= 0) + { + iopkt[1] = cout; + write(reqfd, iopkt, 2); + cout = -1; + } + coutfd = reqfd; + break; case 0xFF: /* close */ FD_CLR(reqfd, &openset); close(reqfd); - reqfd = 0; - maxfd = a2fd > srvfd ? a2fd : srvfd; + reqfd = 0; + coutfd = 0; + maxfd = a2fd > srvfd ? a2fd : srvfd; break; default: prlog("a2pid: Unknown Request\n"); diff --git a/src/a2term.c b/src/a2term.c new file mode 100755 index 0000000..c66eea3 --- /dev/null +++ b/src/a2term.c @@ -0,0 +1,83 @@ +#include "a2lib.c" +#include +#define RUN 0 +#define STOP 1 + +int a2cin(int fd, char cin) +{ + unsigned char cinpkt[2]; + cinpkt[0] = 0x96; // keyboard input + cinpkt[1] = cin; + write(fd, cinpkt, 2); + read(fd, cinpkt, 2); + return (cinpkt[0] == 0x9E); +} +int main(int argc, char **argv) +{ + struct termios oldtio,newtio; + fd_set readset, openset; + unsigned char iopkt[2]; + int state = RUN; + int pifd = a2open(argc > 1 ? argv[1] : "127.0.0.1"); + if (pifd < 0) + { + perror("Unable to connect to Apple II Pi"); + exit(EXIT_FAILURE); + } + tcgetattr(STDIN_FILENO, &oldtio); /* save current port settings */ + bzero(&newtio, sizeof(newtio)); + newtio.c_cflag = /*BAUDRATE | CRTSCTS |*/ CS8 | CLOCAL | CREAD; + newtio.c_iflag = IGNPAR; + newtio.c_oflag = 0; + newtio.c_lflag = 0; /* set input mode (non-canonical, no echo,...) */ + newtio.c_cc[VTIME] = 0; /* inter-character timer unused */ + newtio.c_cc[VMIN] = 1; /* blocking read until 1 char received */ + tcsetattr(STDIN_FILENO, TCSANOW, &newtio); + FD_ZERO(&openset); + FD_SET(pifd, &openset); + FD_SET(STDIN_FILENO, &openset); + /* + * Tell a2pid that we want Apple II character output. + */ + iopkt[0] = 0x98; + write(pifd, iopkt, 1); + /* + * Event loop + */ + while (state == RUN) + { + memcpy(&readset, &openset, sizeof(openset)); + if (select(pifd + 1, &readset, NULL, NULL, NULL) > 0) + { + /* + * Apple II character output. + */ + if (FD_ISSET(pifd, &readset)) + { + if (read(pifd, iopkt, 2) == 2) + { + if (iopkt[0] == 0x98) + { + putchar(iopkt[1] & 0x7F); + if (iopkt[1] == 0x8D) + putchar('\n'); + fflush(stdout); + } + } + } + if (FD_ISSET(STDIN_FILENO, &readset)) + { + if (read(STDIN_FILENO, iopkt, 1) == 1) + { + if (iopkt[0] == 0x1B) + state = STOP; + else + a2cin(pifd, iopkt[0] | 0x80); + } + } + } + } + tcsetattr(STDIN_FILENO, TCSANOW, &oldtio); + a2close(pifd); + return EXIT_SUCCESS; +} \ No newline at end of file