From 8a14d6570b6d913b207f91afbf5a00dbb2dd334c Mon Sep 17 00:00:00 2001 From: dschmenk Date: Tue, 10 Sep 2013 11:27:39 -0700 Subject: [PATCH] Add Koala Pad support and fix //c gameport/mouse init --- src/A2PI.PO | Bin 143360 -> 143360 bytes src/Makefile | 2 +- src/a2joymou.c | 32 ++++---- src/a2joypad.c | 194 +++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 208 insertions(+), 20 deletions(-) create mode 100755 src/a2joypad.c diff --git a/src/A2PI.PO b/src/A2PI.PO index 3e11e1be834ab132f1d80453446d20fa55992824..d1b0b8dffb1a7d710593601d52b836034a4482bb 100755 GIT binary patch delta 467 zcmZp8z|ru4V*?{Aiy(uR++H4zFXn)m4gar&tJWC{%kLt zbNS5qD^T9$%ZGuyO(FapjBT44xjry*z+^VF+zVuyT=F2e{>FkO#||Cd(7WK!xuXkC zo;!I3Xx_#JyA{rzzoM{y{o&pPr!HRtDcN`wD0u1U!6ORC51u`$aQOVWE0@lnIdk+< z?}Eb@ZZ257r9iIUe;}T*TlN$3(MrD&vl!AG;wZYVoYY%Xyu&7uuI9gw5TXG zuS6j^KQApa-Ac*&k%qaMh308PGlp)?1q{0wc2DnMWz=VUGJOXtqlWA!&N~b{feLhj zPXSekaXn+$^<2Y5(^|oL*v4Me(kBX%dgUogT4#roE Y%eWYsrZ+J%*0(?4V%+|Ki>Xl=0AXS7%K!iX delta 328 zcmZp8z|ru4V*?{AivYtK*~zS|vlt~dFJLWTV`Sbe$aBJ7eZl1`2N#?@fA!M&v%N6( z z>+4LL>)ti7PWn-|=nKo{x*tuP(|8!`w=*&^CNZl5ISjj$oJ)&}Qu9g_lJoP@GSjV; ztRHEZn^|ZwbZ{$!%BrnQn& zuw$63f{UwL@G>?=CJ7(^5FJMqV*>*n9~Da_1~D!j#s&rk29eEzY%ds>aWOKrJMb`W Oci>?e*DR)!(~ diff --git a/src/Makefile b/src/Makefile index 88ad371..903d6c6 100755 --- a/src/Makefile +++ b/src/Makefile @@ -1,4 +1,4 @@ -BIN= a2serclk a2pid a2joy a2joymou a2mon a2term dskread dskwrite bintomon bload brun text2merlin merlin2text +BIN= a2serclk a2pid a2joy a2joymou a2joypad a2mon a2term dskread dskwrite bintomon bload brun text2merlin merlin2text all: $(BIN) fusea2pi: fusea2pi.c a2lib.c diff --git a/src/a2joymou.c b/src/a2joymou.c index f127910..80a3e0a 100755 --- a/src/a2joymou.c +++ b/src/a2joymou.c @@ -1,4 +1,4 @@ - /* +/* * Copyright 2013, David Schmenk */ #include "a2lib.c" @@ -8,7 +8,7 @@ #include #define FALSE 0 #define TRUE (!FALSE) -#define POLL_HZ 30 /* must be greater than 1 */ +#define POLL_HZ 60 /* must be greater than 1 */ struct timespec tv; struct input_event evkey, evrelx, evrely, evsync; #define BTTN_IO 0xC061 @@ -146,6 +146,10 @@ void main(int argc, char **argv) evrelx.value = (relx - cntrx) / 2; else evrelx.value = -accel[cntrx - relx]; + write(joyfd, &evrelx, sizeof(evrelx)); + write(joyfd, &evrely, sizeof(evrely)); + write(joyfd, &evsync, sizeof(evsync)); + if (isdebug) fprintf(stderr, "a2joymou (%d, %d) [%d %d]\n", relx, rely, bttns[0] >> 7, bttns[1] >> 7); } else { @@ -159,27 +163,17 @@ void main(int argc, char **argv) else evrely.value = -accel[cntry - rely]; } - a2read(pifd, BTTN_IO, 2, bttns); gptoggle ^= 1; - if (isdebug) fprintf(stderr, "a2joymou (%d, %d) [%d %d]\n", relx, rely, bttns[0] >> 7, bttns[1] >> 7); - write(joyfd, &evrelx, sizeof(evrelx)); - write(joyfd, &evrely, sizeof(evrely)); - write(joyfd, &evsync, sizeof(evsync)); - if ((bttns[0] & 0x80) != prevbttns[0]) + a2read(pifd, BTTN_IO, 2, bttns); + if ((bttns[0] & 0x80) != prevbttns[0]) { + if (!evkey.value) + evkey.code = (bttns[1] & 0x80) ? BTN_RIGHT : BTN_LEFT; + evkey.value = bttns[0] >> 7; + write(joyfd, &evkey, sizeof(evkey)); + write(joyfd, &evsync, sizeof(evsync)); prevbttns[0] = bttns[0] & 0x80; - evkey.code = BTN_LEFT; - evkey.value = bttns[0] >> 7; - write(joyfd, &evkey, sizeof(evkey)); - write(joyfd, &evsync, sizeof(evsync)); - } - if ((bttns[1] & 0x80) != prevbttns[1]) - { prevbttns[1] = bttns[1] & 0x80; - evkey.code = BTN_RIGHT; - evkey.value = bttns[1] >> 7; - write(joyfd, &evkey, sizeof(evkey)); - write(joyfd, &evsync, sizeof(evsync)); } nanosleep(&tv, NULL); } diff --git a/src/a2joypad.c b/src/a2joypad.c new file mode 100755 index 0000000..48eb366 --- /dev/null +++ b/src/a2joypad.c @@ -0,0 +1,194 @@ + /* + * Copyright 2013, David Schmenk + */ +#include "a2lib.c" +#include +#include +#include +#include +#define FALSE 0 +#define TRUE (!FALSE) +#define POLL_HZ 60 /* must be greater than 1 */ +struct timespec tv; +struct input_event evkey, evrelx, evrely, evsync; +#define PEN_UP 0 +#define PEN_DOWN 1 +#define BTTN_IO 0xC061 +#define READGP0 0x380 +#define READGP1 0x388 +char readgp[] = { + 0xA2, 0x00, // LDX #PADDLE + 0x78, // SEI + 0x20, 0x1E, 0xFB, // JSR PREAD + 0x98, // TYA + 0x60, // RTS +}; +int accel[20] = {0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 3, 3, 4, 5, 7, 9, 10}; +/* + * Error handling. + */ +int isdebug, stop = FALSE; +#define prdbg(s) do{if(isdebug)fprintf(stderr,(s));}while(0) +#define die(str, args...) do { \ + prdbg(str); \ + exit(-1); \ +} while(0) +static void sig_bye(int signo) +{ + stop = TRUE; +} + +void main(int argc, char **argv) +{ + struct uinput_user_dev uidev; + int a2fd, joyfd, relx, rely, pen, upx, upy, cntrx, cntry, gptoggle; + unsigned char prevbttns[2], bttns[2]; + + int pifd = a2open("127.0.0.1"); + if (pifd < 0) + { + perror("Unable to connect to Apple II Pi"); + exit(EXIT_FAILURE); + } + /* + * Are we running debug? + */ + if ((argc > 1) && (strcmp(argv[1], "-D") == 0)) + { + isdebug = TRUE; + } + else + { + if (daemon(0, 0) != 0) + die("a2joy: daemon() failure"); + isdebug = FALSE; + } + /* + * Create joystick input device + */ + prdbg("a2joy: Create joystick input device\n"); + joyfd = open("/dev/uinput", O_WRONLY | O_NONBLOCK); + if (joyfd < 0) + die("error: uinput open"); + if (ioctl(joyfd, UI_SET_EVBIT, EV_KEY) < 0) + die("error: uinput ioctl EV_KEY"); + if (ioctl(joyfd, UI_SET_KEYBIT, BTN_LEFT) < 0) + die("error: uinput ioctl BTN_LEFT"); + if (ioctl(joyfd, UI_SET_KEYBIT, BTN_RIGHT) < 0) + die("error: uinput ioctl BTN_RIGHT"); + if (ioctl(joyfd, UI_SET_EVBIT, EV_REL) < 0) + die("error: ioctl EV_REL"); + if (ioctl(joyfd, UI_SET_RELBIT, REL_X) < 0) + die("error: ioctl REL_X"); + if (ioctl(joyfd, UI_SET_RELBIT, REL_Y) < 0) + die("error: ioctl REL_Y"); + if (ioctl(joyfd, UI_SET_EVBIT, EV_SYN) < 0) + die("error: ioctl EV_SYN"); + bzero(&uidev, sizeof(uidev)); + snprintf(uidev.name, UINPUT_MAX_NAME_SIZE, "Apple2 Pi Joystick"); + uidev.id.bustype = BUS_RS232; + uidev.id.vendor = 0x05ac; /* apple */ + uidev.id.product = 0x2e; + uidev.id.version = 1; + write(joyfd, &uidev, sizeof(uidev)); + if (ioctl(joyfd, UI_DEV_CREATE) < 0) + die("error: ioctl DEV_CREATE"); + /* + * Initialize event structures. + */ + bzero(&evkey, sizeof(evkey)); + bzero(&evsync, sizeof(evsync)); + bzero(&evrelx, sizeof(evrelx)); + bzero(&evrely, sizeof(evrely)); + evkey.type = EV_KEY; + evrelx.type = EV_REL; + evrelx.code = REL_X; + evrely.type = EV_REL; + evrely.code = REL_Y; + evsync.type = EV_SYN; + /* + * Add signal handlers. + */ + if (signal(SIGINT, sig_bye) == SIG_ERR) + die("signal"); + if (signal(SIGHUP, sig_bye) == SIG_ERR) + die("signal"); + /* + * Set poll rate. + */ + tv.tv_sec = 0; + tv.tv_nsec = isdebug ? 1E+9/2 : 1E+9/POLL_HZ; + /* + * Download 6502 code. + */ + readgp[1] = 0; + a2write(pifd, READGP0, sizeof(readgp), readgp); + readgp[1] = 1; + a2write(pifd, READGP1, sizeof(readgp), readgp); + a2quickcall(pifd, READGP0, &upx); + a2read(pifd, BTTN_IO, 2, prevbttns); + a2quickcall(pifd, READGP1, &upy); + gptoggle = 0; + pen = PEN_UP; + evrelx.value = 0; + evrely.value = 0; + /* + * Poll joystick loop.a + */ + prdbg("a2joypad: Enter poll loop\n"); + while (!stop) + { + if (gptoggle) + { + a2quickcall(pifd, READGP0, &relx); + if (relx == upx && rely == upy) + { + if (pen == PEN_DOWN) + { + evrelx.value = 0; + evrely.value = 0; + write(joyfd, &evrelx, sizeof(evrelx)); + write(joyfd, &evrely, sizeof(evrely)); + write(joyfd, &evsync, sizeof(evsync)); + } + pen = PEN_UP; + } + else if (pen == PEN_UP && (relx != upx && rely != upy)) + { + pen = PEN_DOWN; + cntrx = relx; + cntry = rely; + } + if (pen == PEN_DOWN) + { + evrelx.value = (relx - cntrx); + evrely.value = (rely - cntry); + write(joyfd, &evrelx, sizeof(evrelx)); + write(joyfd, &evrely, sizeof(evrely)); + write(joyfd, &evsync, sizeof(evsync)); + } + if (isdebug) fprintf(stderr, "a2joypad (%d, %d) [%d %d] pen=%d\n", relx, rely, bttns[0] >> 7, bttns[1] >> 7, pen); + } + else + { + a2quickcall(pifd, READGP1, &rely); + } + gptoggle ^= 1; + a2read(pifd, BTTN_IO, 2, bttns); + if ((bttns[0] & 0x80) != prevbttns[0]) + { + if (!evkey.value) + evkey.code = (bttns[1] & 0x80) ? BTN_RIGHT : BTN_LEFT; + evkey.value = bttns[0] >> 7; + write(joyfd, &evkey, sizeof(evkey)); + write(joyfd, &evsync, sizeof(evsync)); + prevbttns[0] = bttns[0] & 0x80; + prevbttns[1] = bttns[1] & 0x80; + } + nanosleep(&tv, NULL); + } + a2close(pifd); + ioctl(joyfd, UI_DEV_DESTROY); + close(joyfd); + prdbg("\na2joypad: Exit\n"); +}