mirror of
https://github.com/dschmenk/apple2pi.git
synced 2024-11-27 17:51:42 +00:00
Bug fixes and joystick drivers!
This commit is contained in:
parent
786e79a756
commit
61a5a50024
12
src/11-joy.conf
Executable file
12
src/11-joy.conf
Executable file
@ -0,0 +1,12 @@
|
|||||||
|
#
|
||||||
|
# Make sure joysticks don't control the mouse
|
||||||
|
#
|
||||||
|
|
||||||
|
Section "InputClass"
|
||||||
|
Identifier "evdev joystick catchall"
|
||||||
|
MatchIsJoystick "off"
|
||||||
|
MatchDevicePath "/dev/input/event*"
|
||||||
|
Driver "evdev"
|
||||||
|
Option "StartMouseEnabled" "False"
|
||||||
|
Option "StartKeysEnabled" "False"
|
||||||
|
EndSection
|
BIN
src/A2PI.PO
BIN
src/A2PI.PO
Binary file not shown.
@ -1,4 +1,4 @@
|
|||||||
BIN=a2serclk a2pid a2mon a2term dskread dskwrite bintomon bload brun text2merlin merlin2text
|
BIN= a2serclk a2pid a2joy a2joymou a2mon a2term dskread dskwrite bintomon bload brun text2merlin merlin2text
|
||||||
all: $(BIN)
|
all: $(BIN)
|
||||||
|
|
||||||
fusea2pi: fusea2pi.c a2lib.c
|
fusea2pi: fusea2pi.c a2lib.c
|
||||||
|
177
src/a2joy.c
Executable file
177
src/a2joy.c
Executable file
@ -0,0 +1,177 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2013, David Schmenk
|
||||||
|
*/
|
||||||
|
#include "a2lib.c"
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <linux/input.h>
|
||||||
|
#include <linux/uinput.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#define FALSE 0
|
||||||
|
#define TRUE (!FALSE)
|
||||||
|
#define POLL_HZ 20 /* must be greater than 1 */
|
||||||
|
struct timespec tv;
|
||||||
|
struct input_event evkey, evabsx, evabsy, evsync;
|
||||||
|
#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
|
||||||
|
};
|
||||||
|
/*
|
||||||
|
* 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, absx, absy, 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_TRIGGER) < 0)
|
||||||
|
die("error: uinput ioctl BTN_LEFT");
|
||||||
|
if (ioctl(joyfd, UI_SET_KEYBIT, BTN_THUMB) < 0)
|
||||||
|
die("error: uinput ioctl BTN_RIGHT");
|
||||||
|
if (ioctl(joyfd, UI_SET_EVBIT, EV_ABS) < 0)
|
||||||
|
die("error: ioctl EV_ABS");
|
||||||
|
if (ioctl(joyfd, UI_SET_ABSBIT, ABS_X) < 0)
|
||||||
|
die("error: ioctl ABS_X");
|
||||||
|
if (ioctl(joyfd, UI_SET_ABSBIT, ABS_Y) < 0)
|
||||||
|
die("error: ioctl ABS_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;
|
||||||
|
uidev.absmax[0] = 255;
|
||||||
|
uidev.absmin[0] = 0;
|
||||||
|
uidev.absfuzz[0] = 0;
|
||||||
|
uidev.absflat[0] = 0;
|
||||||
|
uidev.absmax[1] = 255;
|
||||||
|
uidev.absmin[1] = 0;
|
||||||
|
uidev.absfuzz[1] = 0;
|
||||||
|
uidev.absflat[1] = 0;
|
||||||
|
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(&evabsx, sizeof(evabsx));
|
||||||
|
bzero(&evabsy, sizeof(evabsy));
|
||||||
|
evkey.type = EV_KEY;
|
||||||
|
evabsx.type = EV_ABS;
|
||||||
|
evabsx.code = ABS_X;
|
||||||
|
evabsy.type = EV_ABS;
|
||||||
|
evabsy.code = ABS_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);
|
||||||
|
a2call(pifd, READGP0, &evabsx.value);
|
||||||
|
a2read(pifd, BTTN_IO, 2, prevbttns);
|
||||||
|
a2call(pifd, READGP1, &evabsy.value);
|
||||||
|
gptoggle = 0;
|
||||||
|
/*
|
||||||
|
* Poll joystick loop.
|
||||||
|
*/
|
||||||
|
prdbg("a2joy: Enter poll loop\n");
|
||||||
|
while (!stop)
|
||||||
|
{
|
||||||
|
if (gptoggle)
|
||||||
|
a2quickcall(pifd, READGP0, &absx);
|
||||||
|
else
|
||||||
|
a2quickcall(pifd, READGP1, &absy);
|
||||||
|
a2read(pifd, BTTN_IO, 2, bttns);
|
||||||
|
gptoggle ^= 1;
|
||||||
|
if (isdebug) fprintf(stderr, "a2joy (%d, %d) [%d %d]\n", absx, absy, bttns[0] >> 7, bttns[1] >> 7);
|
||||||
|
evabsx.value = absx;
|
||||||
|
evabsy.value = absy;
|
||||||
|
write(joyfd, &evabsx, sizeof(evabsx));
|
||||||
|
write(joyfd, &evabsy, sizeof(evabsy));
|
||||||
|
write(joyfd, &evsync, sizeof(evsync));
|
||||||
|
if ((bttns[0] & 0x80) != prevbttns[0])
|
||||||
|
{
|
||||||
|
prevbttns[0] = bttns[0] & 0x80;
|
||||||
|
evkey.code = BTN_TRIGGER;
|
||||||
|
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_THUMB;
|
||||||
|
evkey.value = bttns[1] >> 7;
|
||||||
|
write(joyfd, &evkey, sizeof(evkey));
|
||||||
|
write(joyfd, &evsync, sizeof(evsync));
|
||||||
|
}
|
||||||
|
nanosleep(&tv, NULL);
|
||||||
|
}
|
||||||
|
a2close(pifd);
|
||||||
|
ioctl(joyfd, UI_DEV_DESTROY);
|
||||||
|
close(joyfd);
|
||||||
|
prdbg("\na2joy: Exit\n");
|
||||||
|
}
|
190
src/a2joymou.c
Executable file
190
src/a2joymou.c
Executable file
@ -0,0 +1,190 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2013, David Schmenk
|
||||||
|
*/
|
||||||
|
#include "a2lib.c"
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <linux/input.h>
|
||||||
|
#include <linux/uinput.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#define FALSE 0
|
||||||
|
#define TRUE (!FALSE)
|
||||||
|
#define POLL_HZ 30 /* must be greater than 1 */
|
||||||
|
struct timespec tv;
|
||||||
|
struct input_event evkey, evrelx, evrely, evsync;
|
||||||
|
#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, 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);
|
||||||
|
evrelx.value = 0;
|
||||||
|
evrely.value = 0;
|
||||||
|
a2quickcall(pifd, READGP0, &cntrx);
|
||||||
|
a2read(pifd, BTTN_IO, 2, prevbttns);
|
||||||
|
a2quickcall(pifd, READGP1, &cntry);
|
||||||
|
gptoggle = 0;
|
||||||
|
/*
|
||||||
|
* Poll joystick loop.
|
||||||
|
*/
|
||||||
|
prdbg("a2joymou: Enter poll loop\n");
|
||||||
|
while (!stop)
|
||||||
|
{
|
||||||
|
if (gptoggle)
|
||||||
|
{
|
||||||
|
a2quickcall(pifd, READGP0, &relx);
|
||||||
|
if (relx >= cntrx + 20)
|
||||||
|
evrelx.value = (relx - cntrx) / 2;
|
||||||
|
else if (relx >= cntrx)
|
||||||
|
evrelx.value = accel[relx - cntrx];
|
||||||
|
else if (relx <= cntrx - 20)
|
||||||
|
evrelx.value = (relx - cntrx) / 2;
|
||||||
|
else
|
||||||
|
evrelx.value = -accel[cntrx - relx];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
a2quickcall(pifd, READGP1, &rely);
|
||||||
|
if (rely >= cntry + 20)
|
||||||
|
evrely.value = (rely - cntry) / 2;
|
||||||
|
else if (rely >= cntry)
|
||||||
|
evrely.value = accel[rely - cntry];
|
||||||
|
else if (rely <= cntry - 20)
|
||||||
|
evrely.value = (rely - cntry) / 2;
|
||||||
|
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])
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
a2close(pifd);
|
||||||
|
ioctl(joyfd, UI_DEV_DESTROY);
|
||||||
|
close(joyfd);
|
||||||
|
prdbg("\na2joymou: Exit\n");
|
||||||
|
}
|
12
src/a2lib.c
12
src/a2lib.c
@ -76,6 +76,18 @@ int a2write(int fd, int address, int count, char *buffer)
|
|||||||
return ((unsigned char)writepkt[0] == 0x9E);
|
return ((unsigned char)writepkt[0] == 0x9E);
|
||||||
}
|
}
|
||||||
int a2call(int fd, int address, int *result)
|
int a2call(int fd, int address, int *result)
|
||||||
|
{
|
||||||
|
char callpkt[4];
|
||||||
|
callpkt[0] = 0x9A; // call with keyboard flush
|
||||||
|
callpkt[1] = address;
|
||||||
|
callpkt[2] = address >> 8;
|
||||||
|
write(fd, callpkt, 3);
|
||||||
|
read(fd, callpkt, 2);
|
||||||
|
if (result)
|
||||||
|
*result = (unsigned char)callpkt[1];
|
||||||
|
return ((unsigned char)callpkt[0] == 0x9E);
|
||||||
|
}
|
||||||
|
int a2quickcall(int fd, int address, int *result)
|
||||||
{
|
{
|
||||||
char callpkt[4];
|
char callpkt[4];
|
||||||
callpkt[0] = 0x94; // call
|
callpkt[0] = 0x94; // call
|
||||||
|
54
src/a2pid.c
54
src/a2pid.c
@ -186,11 +186,11 @@ int keycode[256] = {
|
|||||||
KEY_X, // x code 78
|
KEY_X, // x code 78
|
||||||
KEY_Y, // y code 79
|
KEY_Y, // y code 79
|
||||||
KEY_Z, // z code 7A
|
KEY_Z, // z code 7A
|
||||||
MOD_SHIFT | KEY_LEFTBRACE, // { code 7B
|
MOD_SHIFT | KEY_LEFTBRACE, // { code 7B
|
||||||
MOD_SHIFT | KEY_BACKSLASH, // | code 7C
|
MOD_SHIFT | KEY_BACKSLASH, // | code 7C
|
||||||
MOD_SHIFT | KEY_RIGHTBRACE, // } code 7D
|
MOD_SHIFT | KEY_RIGHTBRACE, // } code 7D
|
||||||
MOD_SHIFT | KEY_GRAVE, // ~ code 7E
|
MOD_SHIFT | KEY_GRAVE, // ~ code 7E
|
||||||
KEY_BACKSPACE, // BS code 7F
|
KEY_BACKSPACE, // BS code 7F
|
||||||
/*
|
/*
|
||||||
* w/ closed apple scancodes
|
* w/ closed apple scancodes
|
||||||
*/
|
*/
|
||||||
@ -323,6 +323,7 @@ int keycode[256] = {
|
|||||||
MOD_SHIFT | KEY_GRAVE, // ~ code 7E
|
MOD_SHIFT | KEY_GRAVE, // ~ code 7E
|
||||||
KEY_DELETE // DELETE code 7F
|
KEY_DELETE // DELETE code 7F
|
||||||
};
|
};
|
||||||
|
#define KEYCODE_MAX 0x10000
|
||||||
#define RUN 0
|
#define RUN 0
|
||||||
#define STOP 1
|
#define STOP 1
|
||||||
#define RESET 2
|
#define RESET 2
|
||||||
@ -400,18 +401,18 @@ void sendkey(int fd, int mod, int key)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
sendkeycodedown(fd, code);
|
if (code != -prevkeycode) /* key may have been released before client call */
|
||||||
if (!(key & KEY_PRESS))
|
{
|
||||||
/*
|
sendkeycodedown(fd, code);
|
||||||
* missed a key down event
|
if (!(key & KEY_PRESS))
|
||||||
* already synthesized one
|
/*
|
||||||
*/
|
* missed a key down event
|
||||||
sendkeycodeup(fd, code);
|
* already synthesized one
|
||||||
|
*/
|
||||||
|
sendkeycodeup(fd, code);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
prevkeycode = (key & KEY_PRESS) ? code : -1;
|
prevkeycode = (key & KEY_PRESS) ? code : -KEYCODE_MAX;
|
||||||
}
|
|
||||||
void flushkey(int fd)
|
|
||||||
{
|
|
||||||
}
|
}
|
||||||
void sendbttn(int fd, int mod, int bttn)
|
void sendbttn(int fd, int mod, int bttn)
|
||||||
{
|
{
|
||||||
@ -880,21 +881,22 @@ reset:
|
|||||||
else
|
else
|
||||||
state = RESET;
|
state = RESET;
|
||||||
break;
|
break;
|
||||||
|
case 0x9A: /* acknowledge call with keyboard flush*/
|
||||||
|
if (prevkeycode >= 0) /* flush keyboard if going away for awhile */
|
||||||
|
{
|
||||||
|
sendkeycodeup(kbdfd, prevkeycode);
|
||||||
|
prevkeycode = -prevkeycode;
|
||||||
|
}
|
||||||
case 0x94: /* acknowledge call */
|
case 0x94: /* acknowledge call */
|
||||||
if (a2reqlist) /* better have an outstanding request */
|
if (a2reqlist) /* better have an outstanding request */
|
||||||
{
|
{
|
||||||
//printf("a2pid: call address 0x%04X\n", a2reqlist->addr);
|
//printf("a2pid: call address 0x%04X\n", a2reqlist->addr);
|
||||||
newtio.c_cc[VMIN] = 1; /* blocking read until 1 char received */
|
newtio.c_cc[VMIN] = 1; /* blocking read until 1 char received */
|
||||||
tcsetattr(a2fd, TCSANOW, &newtio);
|
tcsetattr(a2fd, TCSANOW, &newtio);
|
||||||
if (!writeword(a2fd, a2reqlist->addr, 0x95))
|
if (!writeword(a2fd, a2reqlist->addr, iopkt[0] + 1))
|
||||||
state = RESET;
|
state = RESET;
|
||||||
newtio.c_cc[VMIN] = 3; /* blocking read until 3 chars received */
|
newtio.c_cc[VMIN] = 3; /* blocking read until 3 chars received */
|
||||||
tcsetattr(a2fd, TCSANOW, &newtio);
|
tcsetattr(a2fd, TCSANOW, &newtio);
|
||||||
if (prevkeycode >= 0)
|
|
||||||
{
|
|
||||||
sendkeycodeup(kbdfd, prevkeycode);
|
|
||||||
prevkeycode = -1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
state = RESET;
|
state = RESET;
|
||||||
@ -917,6 +919,7 @@ reset:
|
|||||||
for (i = 0; i < MAX_CLIENT; i++)
|
for (i = 0; i < MAX_CLIENT; i++)
|
||||||
if (a2client[i].flags & CLIENT_COUT)
|
if (a2client[i].flags & CLIENT_COUT)
|
||||||
write(a2client[i].fd, iopkt, 2);
|
write(a2client[i].fd, iopkt, 2);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case 0x9E: /* request complete ok */
|
case 0x9E: /* request complete ok */
|
||||||
case 0x9F: /* request complete error */
|
case 0x9F: /* request complete error */
|
||||||
@ -1033,10 +1036,11 @@ reset:
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 0x94: /* call */
|
case 0x94: /* call */
|
||||||
if (read(a2client[i].fd, iopkt, 2) == 2)
|
case 0x9A: /* call with keyboard flush */
|
||||||
|
if (read(a2client[i].fd, iopkt + 1, 2) == 2)
|
||||||
{
|
{
|
||||||
addr = (unsigned char)iopkt[0] | ((unsigned char)iopkt[1] << 8);
|
addr = (unsigned char)iopkt[1] | ((unsigned char)iopkt[2] << 8);
|
||||||
addreq(a2fd, i, 0x94, addr, 0, NULL);
|
addreq(a2fd, i, iopkt[0], addr, 0, NULL);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 0x96: /* send input char to Apple II */
|
case 0x96: /* send input char to Apple II */
|
||||||
|
@ -956,7 +956,6 @@ static int a2pi_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
|
|||||||
/*
|
/*
|
||||||
* Root directory, fill with volume names.
|
* Root directory, fill with volume names.
|
||||||
*/
|
*/
|
||||||
memset(&straw, 0, sizeof(struct stat));
|
|
||||||
unix_stat(&stentry, 0x0F, 0xC3, 0, 0, 0, 0);
|
unix_stat(&stentry, 0x0F, 0xC3, 0, 0, 0, 0);
|
||||||
filler(buf, ".", &stentry, 0);
|
filler(buf, ".", &stentry, 0);
|
||||||
filler(buf, "..", &stentry, 0);
|
filler(buf, "..", &stentry, 0);
|
||||||
@ -969,17 +968,22 @@ static int a2pi_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
|
|||||||
strncpy(filename, volumes + i + 1, l);
|
strncpy(filename, volumes + i + 1, l);
|
||||||
filename[l] = '\0';
|
filename[l] = '\0';
|
||||||
filler(buf, filename, &stentry, 0);
|
filler(buf, filename, &stentry, 0);
|
||||||
|
}
|
||||||
|
memset(&straw, 0, sizeof(struct stat));
|
||||||
|
for (i = 0; i < 16; i++)
|
||||||
|
if (volblks[i] > 0)
|
||||||
|
{
|
||||||
/*
|
/*
|
||||||
* Add volume raw device.
|
* Add raw device.
|
||||||
*/
|
*/
|
||||||
slot = (volumes[i] >> 4) & 0x07;
|
slot = i & 0x07;
|
||||||
drive = (volumes[i] >> 7) & 0x01;
|
drive = (i >> 3) & 0x01;
|
||||||
strcpy(filename, "s0d0.po");
|
strcpy(filename, "s0d0.po");
|
||||||
filename[1] = slot + '0';
|
filename[1] = slot + '0';
|
||||||
filename[3] = drive + '1';
|
filename[3] = drive + '1';
|
||||||
straw.st_mode = S_IFREG | 0644;
|
straw.st_mode = S_IFREG | 0644;
|
||||||
straw.st_nlink = 1;
|
straw.st_nlink = 1;
|
||||||
straw.st_blocks = volblks[slot | (drive << 3)];
|
straw.st_blocks = volblks[i];
|
||||||
straw.st_size = straw.st_blocks * 512;
|
straw.st_size = straw.st_blocks * 512;
|
||||||
filler(buf, filename, &straw, 0);
|
filler(buf, filename, &straw, 0);
|
||||||
}
|
}
|
||||||
@ -1342,6 +1346,13 @@ int main(int argc, char *argv[])
|
|||||||
prodos_get_file_info(volpath, &access, &type, &aux, &storage, &numblks, &mod, &create);
|
prodos_get_file_info(volpath, &access, &type, &aux, &storage, &numblks, &mod, &create);
|
||||||
volblks[volumes[i] >> 4] = aux;
|
volblks[volumes[i] >> 4] = aux;
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
|
* Always add 5 1/4 floppy raw devices.
|
||||||
|
*/
|
||||||
|
if (volblks[0x06] == 0)
|
||||||
|
volblks[0x06] = 280;
|
||||||
|
if (volblks[0x0E] == 0)
|
||||||
|
volblks[0x0E] = 280;
|
||||||
umask(0);
|
umask(0);
|
||||||
return fuse_main(argc, argv, &a2pi_oper, NULL);
|
return fuse_main(argc, argv, &a2pi_oper, NULL);
|
||||||
}
|
}
|
||||||
|
@ -24,4 +24,14 @@ if [ -f /etc/rc.local ] ; then
|
|||||||
sed -e '/^exit/i\# Start Apple II Pi' -e '/^exit/i\/usr/local/bin/a2serclk' -e '/^exit/i\/usr/local/bin/a2pid --daemon' /etc/rc.local.bak > /etc/rc.local
|
sed -e '/^exit/i\# Start Apple II Pi' -e '/^exit/i\/usr/local/bin/a2serclk' -e '/^exit/i\/usr/local/bin/a2pid --daemon' /etc/rc.local.bak > /etc/rc.local
|
||||||
chmod +x /etc/rc.local
|
chmod +x /etc/rc.local
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
#
|
||||||
|
# Disable joystick as a mouse in X
|
||||||
|
#
|
||||||
|
cp 11-joy.conf /usr/share/X11/xorg.conf.d
|
||||||
|
#
|
||||||
|
# Create link to new joystick driver for gsportx
|
||||||
|
#
|
||||||
|
if [ ! -e /dev/js0 ] ; then
|
||||||
|
ln -s /dev/input/js0 /dev/js0
|
||||||
|
fi
|
||||||
|
Loading…
Reference in New Issue
Block a user