--- np2/keystat.c 2004/02/18 03:24:48 1.1 +++ np2/keystat.c 2004/03/30 08:48:46 1.9 @@ -1,307 +1,474 @@ #include "compiler.h" +#include "dosio.h" +#include "textfile.h" #include "pccore.h" #include "iocore.h" #include "keystat.h" +#include "keystat.tbl" -static UINT8 keystat[0x80]; +typedef struct { + UINT8 ref[0x80]; + UINT8 extkey; + UINT8 mouselast; + UINT8 padding; + UINT8 d_up; + UINT8 d_dn; + UINT8 d_lt; + UINT8 d_rt; +} KEYSTAT; -static const UINT8 joykeytable[12] = { - 0x2a, 0x34, - 0x29, 0x1c, - 0x3c, 0x48, - 0x3b, 0x46, - 0x3d, 0x4b, - 0x3a, 0x43}; - -static const UINT8 kbexflag[0x80] = { - // ESC, 1, 2, 3, 4, 5, 6, 7 ; 00h - 0, 0, 0, 0, 0, 0, 0, 0, - // 8, 9, 0, −, ^, ¥, BS, TAB ; 08h - 0, 0, 0, 0, 0, 0, 0, 0, - // Q, W, E, R, T, Y, U, I ; 10h - 0, 0, 0, 0, 0, 0, 0, 0, - // O, P, @, [, Ret, A, S, D ; 18h - 0, 0, 0, 0, 1, 0, 0, 0, - // F, G, H, J, K, L, ;, : ; 20h - 0, 0, 0, 0, 0, 0, 0, 0, - // ], Z, X, C, V, B, N, M ; 28h - 0, 1, 1, 0, 0, 0, 0, 0, - // ,, ., /, _, SPC,XFER,RLUP,RLDN ; 30h - 0, 0, 0, 0, 1, 0, 0, 0, - // INS, DEL, ↑, ←, →, ↓,HMCR,HELP ; 38h - 2, 0, 1, 1, 1, 1, 0, 0, - // <−>,</>,<7>,<8>,<9>,<*>,<4>,<5> ; 40h - 0, 0, 0, 1, 0, 0, 1, 0, - // <6>,<+>,<1>,<2>,<3>,<=>,<0>,<,> ; 48h - 1, 0, 0, 1, 0, 0, 0, 0, - // <.>,NFER,vf.1,vf.2,vf.3,vf.4,vf.5, ; 50h - 0, 0, 2, 2, 2, 2, 2, 0, - // , , , , , ,HOME, ; 58h - 0, 0, 0, 0, 0, 0, 0, 0, - // STOP,COPY, f.1, f.2, f.3, f.4, f.5, f.6 ; 60h - 0, 0, 2, 2, 2, 2, 2, 2, - // f.7, f.8, f.9, f10, , , , ; 68h - 2, 2, 2, 2, 0, 0, 0, 0, - // SFT,CAPS,KANA,GRPH,CTRL, , , ; 70h - 2, 2, 2, 2, 2, 0, 0, 0, - // , , , , , , , ; 78h - 0, 0, 0, 0, 0, 0, 0, 0}; + NKEYTBL nkeytbl; + KEYCTRL keyctrl; +static KEYSTAT keystat; -// ---- +void keystat_initialize(void) { -void keystat_reset(void) { + char path[MAX_PATH]; - ZeroMemory(keystat, sizeof(keystat)); + ZeroMemory(&keystat, sizeof(keystat)); + FillMemory(keystat.ref, sizeof(keystat.ref), NKEYREF_NC); + keystat_tblreset(); + getbiospath(path, "key.txt", sizeof(path)); + keystat_tblload(path); } -void keystat_senddata(REG8 data) { +void keystat_tblreset(void) { + + UINT i; + + ZeroMemory(&nkeytbl, sizeof(nkeytbl)); + for (i=0; i<0x80; i++) { + nkeytbl.key[i].keys = 1; + nkeytbl.key[i].key[0] = (UINT8)i; + } + for (i=0; i<0x10; i++) { + nkeytbl.key[i+0x80].keys = 1; + nkeytbl.key[i+0x80].key[0] = (UINT8)(i + 0xf0); + } +} + +void keystat_tblset(REG8 ref, const UINT8 *key, UINT cnt) { + + NKEYM *nkey; + + if ((ref >= NKEY_USER) && (ref < (NKEY_USER + NKEY_USERKEYS))) { + nkey = (NKEYM *)(nkeytbl.user + (ref - NKEY_USER)); + cnt = min(cnt, 15); + } + else if (ref < NKEY_SYSTEM) { + nkey = (NKEYM *)(nkeytbl.key + ref); + cnt = min(cnt, 3); + } + else { + return; + } + nkey->keys = (UINT8)cnt; + if (cnt) { + CopyMemory(nkey->key, key, cnt); + } +} + + +// ---- config... + +static const char str_userkey1[] = "userkey1"; +static const char str_userkey2[] = "userkey2"; + +static REG8 searchkeynum(const char *str, BOOL user) { + +const KEYNAME *n; +const KEYNAME *nterm; + + n = keyname; + nterm = keyname + (sizeof(keyname) / sizeof(KEYNAME)); + while(n < nterm) { + if (!milstr_cmp(n->str, str)) { + return(n->num); + } + n++; + } + if (user) { + if (!milstr_cmp(str_userkey1, str)) { + return(NKEY_USER + 0); + } + if (!milstr_cmp(str_userkey2, str)) { + return(NKEY_USER + 1); + } + } + return(0xff); +} + +void keystat_tblload(const char *filename) { - REG8 key; - BOOL keynochange; -const _NKEYM *user; - UINT i; - - key = data & 0x7f; - keynochange = FALSE; - - // CTRL:カナ 0x71,0x72 bit7==0でトグル処理 (標準処理) - if ((key == 0x71) || (key == 0x72)) { - if (data & 0x80) { - return; - } - data = key | (keystat[key] & 0x80); - keystat[key] ^= 0x80; - } - else if ((key == 0x76) || (key == 0x77)) { // user key - user = np2cfg.userkey + (key - 0x76); - for (i=0; ikeys; i++) { - key = user->key[i] & 0x7f; - if (!((keystat[key] ^ data) & 0x80)) { - keystat[key] ^= 0x80; - keyboard_send((REG8)(key | (data & 0x80))); + TEXTFILEH tfh; + char work[256]; + char *p; + char *q; + char *r; + UINT8 ref; + UINT8 key[15]; + UINT cnt; + + tfh = textfile_open(filename, 0x800); + if (tfh == NULL) { + goto kstbl_err; + } + while(textfile_read(tfh, work, sizeof(work)) == SUCCESS) { + p = milstr_nextword(work); + q = milstr_chr(p, '\t'); + if (q == NULL) { + q = milstr_chr(p, '='); + } + if (q == NULL) { + continue; + } + *q++ = '\0'; + r = milstr_chr(p, ' '); + if (r != NULL) { + *r = '\0'; + } + ref = searchkeynum(p, TRUE); + if (ref == 0xff) { + continue; + } + cnt = 0; + while((q) && (cnt < 16)) { + p = milstr_nextword(q); + q = milstr_chr(p, ' '); + if (q != NULL) { + *q++ = '\0'; + } + key[cnt] = searchkeynum(p, FALSE); + if (key[cnt] != 0xff) { + cnt++; } } - return; + keystat_tblset(ref, key, cnt); + } + textfile_close(tfh); + +kstbl_err: + return; +} + + +// ---- + +void keystat_ctrl(REG8 dat) { + + return; // まだBIOSが未対応 + + if (!keyctrl.reqparam) { + keyctrl.mode = dat; + switch(dat) { +#if defined(SUPPORT_PC9801_119) + case 0x95: +#endif + case 0x9c: + case 0x9d: + keyctrl.reqparam = 1; + keyboard_ctrl(0xfa); + break; + +#if defined(SUPPORT_PC9801_119) + case 0x96: + keyboard_ctrl(0xfa); + keyboard_ctrl(0xa0); + keyboard_ctrl(0x83); + break; +#endif + + case 0x9f: + keyboard_ctrl(0xfa); + keyboard_ctrl(0xa0); + keyboard_ctrl(0x80); + break; + + default: + keyboard_ctrl(0xfc); + break; + } } else { - if ((np2cfg.XSHIFT) && - (((key == 0x70) && (np2cfg.XSHIFT & 1)) || - ((key == 0x74) && (np2cfg.XSHIFT & 2)) || - ((key == 0x73) && (np2cfg.XSHIFT & 4)))) { - if (data & 0x80) { - return; + switch(keyctrl.mode) { +#if defined(SUPPORT_PC9801_119) + case 0x95: + keyctrl.kbdtype = dat; + break; +#endif + case 0x9d: + break; + + case 0x9e: + break; + } + keyctrl.reqparam = 0; + } +} + + +// ---- + +void keystat_down(const UINT8 *key, REG8 keys, REG8 ref) { + + UINT8 keydata; + UINT8 keycode; + REG8 data; + + while(keys--) { + keydata = *key++; + keycode = (keydata & 0x7f); + if (keycode < 0x70) { + if ((keystat.ref[keycode] == NKEYREF_NC) || + (!(kbexflag[keycode] & KBEX_NONREP))) { + keyboard_send(keycode); } - data = key | (keystat[key] & 0x80); - keystat[key] ^= 0x80; + keystat.ref[keycode] = ref; } else { - // CTRL:カナ 0x79,0x7a bit7をそのまま通知 - // (ハードウェアでメカニカル処理してる場合) - if ((key == 0x79) || (key == 0x7a)) { - key -= 0x08; - data -= 0x08; - } - if (!((keystat[key] ^ data) & 0x80)) { - keystat[key] ^= 0x80; - } - else { - keynochange = TRUE; - if (kbexflag[key] & 2) { // キーリピート無し - return; +#if defined(SUPPORT_PC9801_119) + if ((keyctrl.kbdtype != 0x03) && (keycode >= 0x75)) { + continue; + } +#else + if (keycode >= 0x75) { + continue; + } +#endif + if ((np2cfg.XSHIFT) && + (((keycode == 0x70) && (np2cfg.XSHIFT & 1)) || + ((keycode == 0x74) && (np2cfg.XSHIFT & 2)) || + ((keycode == 0x73) && (np2cfg.XSHIFT & 4)))) { + keydata |= 0x80; + } + if (!(keydata & 0x80)) { // シフト + if (keystat.ref[keycode] == NKEYREF_NC) { + keystat.ref[keycode] = ref; + keyboard_send(keycode); } } - } - } - if ((!np2cfg.KEY_MODE) || (!(kbexflag[key] & 1))) { - if (keynochange) { - if (data & 0x80) { // ver0.30 - return; + else { // シフトメカニカル処理 + if (keystat.ref[keycode] == NKEYREF_NC) { + keystat.ref[keycode] = ref; + data = keycode; + } + else { + keystat.ref[keycode] = NKEYREF_NC; + data = (REG8)(keycode + 0x80); + } + keyboard_send(data); } - keyboard_send((REG8)(data ^ 0x80)); } - keyboard_send(data); } } -void keystat_forcerelease(REG8 value) { +void keystat_up(const UINT8 *key, REG8 keys, REG8 ref) { - REG8 key; -const _NKEYM *user; - UINT i; + UINT8 keydata; + UINT8 keycode; - key = value & 0x7f; - if ((key != 0x76) && (key != 0x77)) { - if (keystat[key] & 0x80) { - keystat[key] &= ~0x80; - keyboard_send((REG8)(key | 0x80)); + while(keys--) { + keydata = *key++; + keycode = (keydata & 0x7f); + if (keycode < 0x70) { + if (keystat.ref[keycode] == ref) { + keystat.ref[keycode] = NKEYREF_NC; + keyboard_send((REG8)(keycode + 0x80)); + } } - } - else { - user = np2cfg.userkey + (key - 0x76); - for (i=0; ikeys; i++) { - key = user->key[i] & 0x7f; - if (keystat[key] & 0x80) { - keystat[key] &= ~0x80; - keyboard_send((REG8)(key | 0x80)); + else { +#if defined(SUPPORT_PC9801_119) + if ((keyctrl.kbdtype != 0x03) && (keycode >= 0x75)) { + continue; + } +#else + if (keycode >= 0x75) { + continue; + } +#endif + if ((np2cfg.XSHIFT) && + (((keycode == 0x70) && (np2cfg.XSHIFT & 1)) || + ((keycode == 0x74) && (np2cfg.XSHIFT & 2)) || + ((keycode == 0x73) && (np2cfg.XSHIFT & 4)))) { + keydata |= 0x80; + } + if (!(keydata & 0x80)) { // シフト + if (keystat.ref[keycode] != NKEYREF_NC) { + keystat.ref[keycode] = NKEYREF_NC; + keyboard_send((REG8)(keycode + 0x80)); + } } } } } -void keystat_resetcopyhelp(void) { +void keystat_resendstat(void) { REG8 i; - for (i=0x60; i<0x62; i++) { - if (keystat[i] & 0x80) { - keystat[i] &= 0x7f; - keyboard_send((REG8)(i | 0x80)); + for (i=0; i<0x80; i++) { + if (keystat.ref[i] != NKEYREF_NC) { + keyboard_send(i); } } } -void keystat_allrelease(void) { - REG8 i; +// ---- - for (i=0; i<0x80; i++) { - if (keystat[i] & 0x80) { - keystat[i] &= ~0x80; - keyboard_send((REG8)(i | 0x80)); +void keystat_keydown(REG8 ref) { + + UINT8 shift; +const NKEYM *nkey; + + if ((ref >= NKEY_USER) && (ref < (NKEY_USER + NKEY_USERKEYS))) { + nkey = (NKEYM *)(nkeytbl.user + (ref - NKEY_USER)); + keystat_down(nkey->key, nkey->keys, NKEYREF_USER); + } + else if (ref < NKEY_SYSTEM) { + if (np2cfg.KEY_MODE) { + shift = kbexflag[ref]; + if (shift & KBEX_JOYKEY) { + keystat.extkey |= (1 << (shift & 7)); + return; + } } + nkey = (NKEYM *)(nkeytbl.key + ref); + keystat_down(nkey->key, nkey->keys, ref); } } -void keystat_resetjoykey(void) { +void keystat_keyup(REG8 ref) { - int i; - REG8 key; + UINT8 shift; +const NKEYM *nkey; - for (i=0; i<12; i++) { - key = joykeytable[i]; - if (keystat[key] & 0x80) { - keystat[key] &= 0x7f; - keyboard_send((REG8)(key | 0x80)); + if ((ref >= NKEY_USER) && (ref < (NKEY_USER + NKEY_USERKEYS))) { + nkey = (NKEYM *)(nkeytbl.user + (ref - NKEY_USER)); + keystat_up(nkey->key, nkey->keys, NKEYREF_USER); + } + else if (ref < NKEY_SYSTEM) { + if (np2cfg.KEY_MODE) { + shift = kbexflag[ref]; + if (shift & KBEX_JOYKEY) { + keystat.extkey &= ~(1 << (shift & 7)); + return; + } } + nkey = (NKEYM *)(nkeytbl.key + ref); + keystat_up(nkey->key, nkey->keys, ref); } } -void keystat_resendstat(void) { +void keystat_releaseref(REG8 ref) { - int i; + REG8 i; for (i=0; i<0x80; i++) { - if (keystat[i]) { - keyboard_send((REG8)i); + if (keystat.ref[i] == ref) { + keystat.ref[i] = NKEYREF_NC; + keyboard_send((REG8)(i + 0x80)); } } } +void keystat_resetjoykey(void) { -// ---- + REG8 i; -typedef struct { - UINT8 joysync; - UINT8 joylast; - UINT8 mouselast; - UINT8 padding; - UINT8 d_up; - UINT8 d_dn; - UINT8 d_lt; - UINT8 d_rt; -} KEYEXT; + keystat.extkey = 0; + for (i=0; i<0x80; i++) { + if (kbexflag[i] & KBEX_JOYKEY) { + keystat_releaseref(i); + } + } +} -static KEYEXT keyext; -static const UINT8 mousedelta[] = {1, 1, 1, 1, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 4}; -#define MOUSESTEPMAX ((sizeof(mousedelta) / sizeof(UINT8)) - 1) -void keystat_sync(void) { +void keystat_releasekey(REG8 key) { - keyext.joysync = 0; + key &= 0x7f; + if (keystat.ref[key] != NKEYREF_NC) { + keystat.ref[key] = NKEYREF_NC; + keyboard_send((REG8)(key + 0x80)); + } } -REG8 keystat_getjoy(void) { +void keystat_allrelease(void) { - BYTE flg; -const BYTE *p; - BYTE bit; - - if (!keyext.joysync) { - keyext.joysync = 1; - flg = 0xff; - p = joykeytable; - for (bit=0x20; bit; bit>>=1) { - if ((keystat[p[0]] & 0x80) || (keystat[p[1]] & 0x80)) { - flg ^= bit; - } - p += 2; - } - keyext.joylast = flg; + REG8 i; + + for (i=0; i<0x80; i++) { + keystat_releasekey(i); } - return(keyext.joylast); +} + + +REG8 keystat_getjoy(void) { + + return(~keystat.extkey); } REG8 keystat_getmouse(SINT16 *x, SINT16 *y) { REG8 btn; - BYTE acc; + UINT8 acc; SINT16 tmp; - BYTE ret; + REG8 ret; - btn = keystat_getjoy(); - acc = btn | keyext.mouselast; - keyext.mouselast = (UINT8)btn; + btn = ~keystat.extkey; + acc = btn | keystat.mouselast; + keystat.mouselast = (UINT8)btn; tmp = 0; if (!(btn & 1)) { - tmp -= mousedelta[keyext.d_up]; + tmp -= mousedelta[keystat.d_up]; } if (!(acc & 1)) { - if (keyext.d_up < MOUSESTEPMAX) { - keyext.d_up++; + if (keystat.d_up < MOUSESTEPMAX) { + keystat.d_up++; } } else { - keyext.d_up = 0; + keystat.d_up = 0; } if (!(btn & 2)) { - tmp += mousedelta[keyext.d_dn]; + tmp += mousedelta[keystat.d_dn]; } if (!(acc & 2)) { - if (keyext.d_dn < MOUSESTEPMAX) { - keyext.d_dn++; + if (keystat.d_dn < MOUSESTEPMAX) { + keystat.d_dn++; } } else { - keyext.d_dn = 0; + keystat.d_dn = 0; } *y += tmp; tmp = 0; if (!(btn & 4)) { - tmp -= mousedelta[keyext.d_lt]; + tmp -= mousedelta[keystat.d_lt]; } if (!(acc & 4)) { - if (keyext.d_lt < MOUSESTEPMAX) { - keyext.d_lt++; + if (keystat.d_lt < MOUSESTEPMAX) { + keystat.d_lt++; } } else { - keyext.d_lt = 0; + keystat.d_lt = 0; } if (!(btn & 8)) { - tmp += mousedelta[keyext.d_rt]; + tmp += mousedelta[keystat.d_rt]; } if (!(acc & 8)) { - if (keyext.d_rt < MOUSESTEPMAX) { - keyext.d_rt++; + if (keystat.d_rt < MOUSESTEPMAX) { + keystat.d_rt++; } } else { - keyext.d_rt = 0; + keystat.d_rt = 0; } *x += tmp; @@ -311,3 +478,55 @@ REG8 keystat_getmouse(SINT16 *x, SINT16 return(ret); } + +// ---- + +// キーコード変更 + +static REG8 cnvnewcode(REG8 oldcode) { + + switch(oldcode) { + case 0x71: // 通常caps + return(0x81); + + case 0x72: // 通常カナ + return(0x82); + + case 0x79: // メカニカルロックcaps + return(0x71); + + case 0x7a: // メカニカルロックcaps + return(0x72); + + case 0x76: + return(0x90); // NKEY_USER + 0 + + case 0x77: + return(0x91); // NKEY_USER + 1 + + default: + return(oldcode); + } +} + +void keystat_senddata(REG8 data) { + + REG8 keycode; + + keycode = cnvnewcode((REG8)(data & 0x7f)); + if (!(data & 0x80)) { + keystat_keydown(keycode); + } + else { + keystat_keyup(keycode); + } +} + +void keystat_forcerelease(REG8 data) { + + REG8 keycode; + + keycode = cnvnewcode((REG8)(data & 0x7f)); + keystat_releasekey(keycode); +} +