/* * UAE - The Un*x Amiga Emulator * * Keyboard buffer. Not really needed for X, but for SVGAlib and possibly * Mac and DOS ports. * * Note: it's possible to have two threads in UAE, one reading keystrokes * and the other one writing them. Despite this, no synchronization effort * is needed. This code should be perfectly thread safe. At least if you * assume that integer store instructions are atomic. * * Copyright 1995, 1997 Bernd Schmidt */ #include "sysconfig.h" #include "sysdeps.h" #include #include "options.h" #include "keybuf.h" #include "keyboard.h" #include "inputdevice.h" #include "custom.h" #include "savestate.h" static int fakestate[2][7] = { {0},{0} }; static int *fs_np; static int *fs_np; static int *fs_ck; static int *fs_se; #ifdef XARCADE static int *fs_xa1; static int *fs_xa2; #endif /* Not static so the DOS code can mess with them */ int kpb_first, kpb_last; static int keybuf[256]; int keys_available (void) { int val; val = kpb_first != kpb_last; return val; } int get_next_key (void) { int key; assert (kpb_first != kpb_last); key = keybuf[kpb_last]; if (++kpb_last == 256) kpb_last = 0; return key; } static void do_fake (int nr) { int *fake = fakestate[nr]; nr = compatibility_device[nr]; setjoystickstate (nr, 0, fake[1] ? -100 : (fake[2] ? 100 : 0), 100); setjoystickstate (nr, 1, fake[0] ? -100 : (fake[3] ? 100 : 0), 100); setjoybuttonstate (nr, 0, fake[4]); setjoybuttonstate (nr, 1, fake[5]); setjoybuttonstate (nr, 2, fake[6]); } void record_key (int kc) { int fs = 0; int kpb_next = kpb_first + 1; int k = kc >> 1; int b = !(kc & 1); //write_log ("got kc %02.2X\n", ((kc << 7) | (kc >> 1)) & 0xff); if (kpb_next == 256) kpb_next = 0; if (kpb_next == kpb_last) { write_log ("Keyboard buffer overrun. Congratulations.\n"); return; } if (fs_np != 0) { switch (kc >> 1) { case AK_NP8: fs = 1; fs_np[0] = !(kc & 1); break; case AK_NP4: fs = 1; fs_np[1] = !(kc & 1); break; case AK_NP6: fs = 1; fs_np[2] = !(kc & 1); break; case AK_NP2: fs = 1; fs_np[3] = !(kc & 1); break; case AK_NP0: case AK_NP5: fs = 1; fs_np[4] = !(kc & 1); break; case AK_NPDEL: case AK_NPDIV: case AK_ENT: fs = 1; fs_np[5] = !(kc & 1); break; } } if (fs_ck != 0) { switch (kc >> 1) { case AK_UP: fs = 1; fs_ck[0] = !(kc & 1); break; case AK_LF: fs = 1; fs_ck[1] = !(kc & 1); break; case AK_RT: fs = 1; fs_ck[2] = !(kc & 1); break; case AK_DN: fs = 1; fs_ck[3] = !(kc & 1); break; case AK_RCTRL: case AK_RALT: fs = 1; fs_ck[4] = !(kc & 1); break; case AK_RSH: fs = 1; fs_ck[5] = !(kc & 1); break; } } if (fs_se != 0) { switch (k) { case AK_T: fs = 1; fs_se[0] = b; break; case AK_F: fs = 1; fs_se[1] = b; break; case AK_H: fs = 1; fs_se[2] = b; break; case AK_B: fs = 1; fs_se[3] = b; break; case AK_LALT: fs = 1; fs_se[4] = b; break; case AK_LSH: fs = 1; fs_se[5] = b; break; } } #ifdef XARCADE if (fs_xa1 != 0) { switch (k) { case AK_NP8: fs = 1; fs_xa1[0] = b; break; case AK_NP4: fs = 1; fs_xa1[1] = b; break; case AK_NP6: fs = 1; fs_xa1[2] = b; break; case AK_NP2: case AK_NP5: fs = 1; fs_xa1[3] = b; break; case AK_CTRL: fs = 1; fs_xa1[4] = b; break; case AK_LALT: fs = 1; fs_xa1[5] = b; break; case AK_SPC: fs = 1; fs_xa1[6] = b; break; } } if (fs_xa2 != 0) { switch (k) { case AK_R: fs = 1; fs_xa2[0] = b; break; case AK_D: fs = 1; fs_xa2[1] = b; break; case AK_G: fs = 1; fs_xa2[2] = b; break; case AK_F: fs = 1; fs_xa2[3] = b; break; case AK_A: fs = 1; fs_xa2[4] = b; break; case AK_S: fs = 1; fs_xa2[5] = b; break; case AK_Q: fs = 1; fs_xa2[6] = b; break; } } #endif if (fs && currprefs.input_selected_setting == 0) { if (JSEM_ISANYKBD (0, &currprefs)) do_fake (0); if (JSEM_ISANYKBD (1, &currprefs)) do_fake (1); return; } else { if ((kc >> 1) == AK_RCTRL) { kc ^= AK_RCTRL << 1; kc ^= AK_CTRL << 1; } #ifdef XARCADE if (fs_xa1 || fs_xa2) { int k2 = k; if (k == AK_1) k2 = AK_F1; if (k == AK_2) k2 = AK_F2; if (k == AK_3) k2 = AK_LALT; if (k == AK_4) k2 = AK_RALT; if (k == AK_6) k2 = AK_DN; if (k == AK_LBRACKET || k == AK_LSH) k2 = AK_SPC; if (k == AK_RBRACKET) k2 = AK_RET; if (k == AK_C) k2 = AK_1; if (k == AK_5) k2 = AK_2; if (k == AK_Z) k2 = AK_3; if (k == AK_X) k2 = AK_4; if (k != k2) kc = (k2 << 1) | (b ? 0 : 1); } #endif } keybuf[kpb_first] = kc; kpb_first = kpb_next; } void joystick_setting_changed (void) { fs_np = fs_ck = fs_se = 0; #ifdef XARCADE fs_xa1 = fs_xa2 = 0; #endif if (JSEM_ISNUMPAD (0, &currprefs)) fs_np = fakestate[0]; else if (JSEM_ISNUMPAD (1, &currprefs)) fs_np = fakestate[1]; if (JSEM_ISCURSOR (0, &currprefs)) fs_ck = fakestate[0]; else if (JSEM_ISCURSOR (1, &currprefs)) fs_ck = fakestate[1]; if (JSEM_ISSOMEWHEREELSE (0, &currprefs)) fs_se = fakestate[0]; else if (JSEM_ISSOMEWHEREELSE (1, &currprefs)) fs_se = fakestate[1]; #ifdef XARCADE if (JSEM_ISXARCADE1 (0, &currprefs)) fs_xa1 = fakestate[0]; else if (JSEM_ISXARCADE1 (1, &currprefs)) fs_xa1 = fakestate[1]; if (JSEM_ISXARCADE2 (0, &currprefs)) fs_xa2 = fakestate[0]; else if (JSEM_ISXARCADE2 (1, &currprefs)) fs_xa2 = fakestate[1]; #endif } void keybuf_init (void) { kpb_first = kpb_last = 0; inputdevice_updateconfig (&currprefs); } #ifdef SAVESTATE uae_u8 *save_keyboard (uae_u32 *len) { uae_u8 *dst, *t; dst = t = malloc (8); save_u32 (getcapslockstate() ? 1 : 0); save_u32 (0); *len = 8; return t; } const uae_u8 *restore_keyboard (const uae_u8 *src) { setcapslockstate (restore_u32 ()); restore_u32 (); return src; } #endif /* SAVESTATE */