Subversion Repositories pentevo

Rev

Rev 979 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed | ?url?

  1. #include "std.h"
  2.  
  3. #include "emul.h"
  4. #include "vars.h"
  5. #include "dx.h"
  6. #include "tape.h"
  7. #include "atm.h"
  8. #include "memory.h"
  9. #include "input.h"
  10. #include "inputpc.h"
  11.  
  12. #include "util.h"
  13.  
  14. static unsigned char pastekeys[0x80-0x20] =
  15. {
  16.    // s     !     "     #     $     %     &     '     (     )     *     +     ,     -   .       /
  17.    0x71, 0xB1, 0xD1, 0xB3, 0xB4, 0xB5, 0xC5, 0xC4, 0xC3, 0xC2, 0xF5, 0xE3, 0xF4, 0xE4, 0xF3, 0x85,
  18.    // 0     1     2     3     4     5     6     7     8     9     :     ;     <     =     >     ?
  19.    0x41, 0x31, 0x32, 0x33, 0x34, 0x35, 0x45, 0x44, 0x43, 0x42, 0x82, 0xD2, 0xA4, 0xE2, 0xA5, 0x84,
  20.    // @     A     B     C     D     E     F     G     H     I     J     K     L     M     N     O
  21.    0xB2, 0x19, 0x7D, 0x0C, 0x1B, 0x2B, 0x1C, 0x1D, 0x6D, 0x5B, 0x6C, 0x6B, 0x6A, 0x7B, 0x7C, 0x5A,
  22.    // P     Q     R     S     T     U     V     W     X     Y     Z     [     \     ]     ^     _
  23.    0x59, 0x29, 0x2C, 0x1A, 0x2D, 0x5C, 0x0D, 0x2A, 0x0B, 0x5D, 0x0A, 0xD5, 0x93, 0xD4, 0xE5, 0xC1,
  24.    // `     a     b     c     d     e     f     g     h     i     j     k     l     m     n     o
  25.    0x83, 0x11, 0x75, 0x04, 0x13, 0x23, 0x14, 0x15, 0x65, 0x53, 0x64, 0x63, 0x62, 0x73, 0x74, 0x52,
  26.    // p     q     r     s     t     u     v     w     x     y     z     {     |     }     ~
  27.    0x51, 0x21, 0x24, 0x12, 0x25, 0x54, 0x05, 0x22, 0x03, 0x55, 0x02, 0x94, 0x92, 0x95, 0x91, 0xC4
  28. }; //`=0x83, 127=' - Alone Coder
  29.  
  30. static unsigned char ruspastekeys[64] =
  31. {
  32.     'A','B','W','G','D','E','V','Z','I','J','K','L','M','N','O','P',
  33.     'R','S','T','U','F','H','C','^','[',']',127,'Y','X','\\',64,'Q',
  34.     'a','b','w','g','d','e','v','z','i','j','k','l','m','n','o','p',
  35.     'r','s','t','u','f','h','c','~','{','}','_','y','x','|','`','q'
  36. }; //Alone Coder
  37.  
  38. void K_INPUT::clear_zx()
  39. {
  40.    size_t i;
  41.    for(i = 0; i < _countof(kbd_x4); i++)
  42.        kbd_x4[i] = -1U;
  43. }
  44.  
  45. inline void K_INPUT::press_zx(unsigned char key)
  46. {
  47.    if (key & 0x08)
  48.        kbd[0] &= ~1; // caps
  49.    if (key & 0x80)
  50.        kbd[7] &= ~2; // sym
  51.    if (key & 7)
  52.        kbd[(key >> 4) & 7] &= ~(1 << ((key & 7) - 1));
  53. }
  54.  
  55. // #include "inputpc.cpp"
  56.  
  57. bool K_INPUT::process_pc_layout()
  58. {
  59.    for (unsigned i = 0; i < pc_layout_count; i++)
  60.    {
  61.       if (kbdpc[pc_layout[i].vkey] & 0x80)
  62.       {
  63.          press_zx(((kbdpc[DIK_LSHIFT] | kbdpc[DIK_RSHIFT]) & 0x80) ? pc_layout[i].shifted : pc_layout[i].normal);
  64.          return true;
  65.       }
  66.    }
  67.    return false;
  68. }
  69.  
  70. void K_INPUT::make_matrix()
  71. {
  72.    unsigned char altlock = conf.input.altlock? (kbdpc[DIK_LMENU] | kbdpc[DIK_RMENU]) & 0x80 : 0;
  73.    size_t i;
  74.  
  75.    kjoy = 0xFF;
  76.    fjoy = 0xFF;
  77.    switch (keymode)
  78.    {
  79.       case KM_DEFAULT:
  80.          clear_zx();
  81.          if (!altlock)
  82.          {
  83.             if (!conf.input.keybpcmode || !process_pc_layout())
  84.             {
  85.                 for (i = 0; i < VK_MAX; i++)
  86.                 {
  87.                    if (kbdpc[i] & 0x80)
  88.                    {
  89.                       *(inports[i].port1) &= inports[i].mask1;
  90.                       *(inports[i].port2) &= inports[i].mask2;
  91. /*
  92.    if(kbd[6] == 0xFE)
  93.        __debugbreak();
  94. */
  95.                    }
  96.                 }
  97.             }
  98.          }
  99.  
  100.          if (conf.input.fire)
  101.          {
  102.              if(!--firedelay)
  103.              {
  104.                  firedelay = conf.input.firedelay;
  105.                  firestate ^= 1;
  106.              }
  107.             zxkeymap *active_zxk = conf.input.active_zxk;
  108.             if (firestate) *(active_zxk->zxk[conf.input.firenum].port) &= active_zxk->zxk[conf.input.firenum].mask;
  109.          }
  110.          break;
  111.  
  112.       case KM_KEYSTICK:
  113.          for(i = 0; i < _countof(kbd_x4); i++)
  114.              kbd_x4[i] = rkbd_x4[i];
  115.          if(stick_delay)
  116.          {
  117.              stick_delay--;
  118.              altlock = 1;
  119.          }
  120.          if(!altlock)
  121.          {
  122.              for(i = 0; i < VK_MAX; i++)
  123.              {
  124.                  if(kbdpc[i] & 0x80)
  125.                  {
  126.                      *(inports[i].port1) ^= ~inports[i].mask1;
  127.                      *(inports[i].port2) ^= ~inports[i].mask2;
  128.                  }
  129.              }
  130.          }
  131.          if ((kbd_x4[0] ^ rkbd_x4[0]) | (kbd_x4[1] ^ rkbd_x4[1])) stick_delay = 10;
  132.          break;
  133.  
  134.       case KM_PASTE_HOLD:
  135.       {
  136.          clear_zx();
  137.          if (tdata & 0x08) kbd[0] &= ~1; // caps
  138.          if (tdata & 0x80) kbd[7] &= ~2; // sym
  139.          if (tdata & 7) kbd[(tdata >> 4) & 7] &= ~(1 << ((tdata & 7) - 1));
  140.          if (tdelay) { tdelay--; break; }
  141.          tdelay = conf.input.paste_release;
  142.          if (tdata == 0x61) tdelay += conf.input.paste_newline;
  143.          keymode = KM_PASTE_RELEASE;
  144.          break;
  145.       }
  146.  
  147.       case KM_PASTE_RELEASE:
  148.       {
  149.          clear_zx();
  150.          if (tdelay) { tdelay--; break; }
  151.          if (textsize == textoffset)
  152.          {
  153.             keymode = KM_DEFAULT;
  154.             free(textbuffer);
  155.             textbuffer = nullptr;
  156.             break;
  157.          }
  158.          tdelay = conf.input.paste_hold;
  159.          unsigned char kdata = textbuffer[textoffset++];
  160.          if (kdata == 0x0D)
  161.          {
  162.             if (textoffset < textsize && textbuffer[textoffset] == 0x0A) textoffset++;
  163.             tdata = 0x61;
  164.          }
  165.          else
  166.          {
  167.             if (kdata == 0xA8) kdata = 'E'; //Alone Coder (big YO)
  168.             if ((kdata >= 0xC0)||(kdata == 0xB8)) //RUS
  169.             {
  170.                 //pressedit=
  171.                 //0 = press edit, pressedit++, textoffset--
  172.                 //1 = press letter, pressedit++, textoffset--
  173.                 //2 = press edit, pressedit=0
  174.                 switch (pressedit)
  175.                 {
  176.                     case 0:
  177.                     {
  178.                         tdata = 0x39;
  179.                         pressedit++;
  180.                         textoffset--;
  181.                         break;
  182.                     };
  183.                     case 1:
  184.                     {
  185.                         if (kdata == 0xB8) kdata = '&';else kdata = ruspastekeys[kdata - 0xC0];
  186.                         tdata = pastekeys[kdata - 0x20];
  187.                         pressedit++;
  188.                         textoffset--;
  189.                         break;
  190.                     }
  191.                     case 2:
  192.                     {
  193.                         tdata = 0x39;
  194.                         pressedit = 0;
  195.                     };
  196.                 };
  197.                 if (!tdata)
  198.                     break; // empty key
  199.             } //Alone Coder
  200.             else
  201.             {
  202.                 if (kdata < 0x20 || kdata >= 0x80) break; // keep release state
  203.                 tdata = pastekeys[kdata - 0x20];
  204.                 if (!tdata) break; // empty key
  205.             }
  206.          }
  207.          keymode = KM_PASTE_HOLD;
  208.          break;
  209.       }
  210.    }
  211.    kjoy ^= 0xFF;
  212.    if (conf.input.joymouse)
  213.        kjoy |= mousejoy;
  214.  
  215.    for(i = 0; i < _countof(kbd_x4); i++)
  216.        rkbd_x4[i] = kbd_x4[i];
  217.    if (!conf.input.keymatrix)
  218.        return;
  219.    for (;;)
  220.    {
  221.       char done = 1;
  222.       for (size_t k = 0; k < _countof(kbd) - 1; k++)
  223.       {
  224.          for (size_t j = k+1; j < _countof(kbd); j++)
  225.          {
  226.             if (((kbd[k] | kbd[j]) != 0xFF) && (kbd[k] != kbd[j]))
  227.             {
  228.                kbd[k] = kbd[j] = (kbd[k] & kbd[j]);
  229.                done = 0;
  230.             }
  231.          }
  232.       }
  233.       if (done)
  234.           return;
  235.    }
  236. }
  237.  
  238. __inline int sign_pm(int a) { return (a < 0)? -1 : 1; }
  239.  
  240. static u8 CapsLockState = 0;
  241.  
  242. char K_INPUT::readdevices()
  243. {
  244.    if (nokb) nokb--;
  245.    if (nomouse) nomouse--;
  246.  
  247.    kbdpc[VK_JLEFT] = kbdpc[VK_JRIGHT] = kbdpc[VK_JUP] = kbdpc[VK_JDOWN] = kbdpc[VK_JFIRE] = 0;
  248.    int i;
  249.    for(i = 0; i < 32; i++)
  250.        kbdpc[VK_JB0 + i] = 0;
  251.    if (active && dijoyst)
  252.    {
  253.       dijoyst->Poll();
  254.       DIJOYSTATE js;
  255.       readdevice(&js, sizeof js, (LPDIRECTINPUTDEVICE)dijoyst);
  256.       if ((signed short)js.lX < 0) kbdpc[VK_JLEFT] = 0x80;
  257.       if ((signed short)js.lX > 0) kbdpc[VK_JRIGHT] = 0x80;
  258.       if ((signed short)js.lY < 0) kbdpc[VK_JUP] = 0x80;
  259.       if ((signed short)js.lY > 0) kbdpc[VK_JDOWN] = 0x80;
  260.  
  261.       for(i = 0; i < 32; i++)
  262.       {
  263.           if (js.rgbButtons[i] & 0x80)
  264.               kbdpc[VK_JB0 + i] = 0x80;
  265.       }
  266.    }
  267.  
  268.    mbuttons = 0xFF;
  269.    msx_prev = msx; msy_prev = msy;
  270.    kbdpc[VK_LMB] = kbdpc[VK_RMB] = kbdpc[VK_MMB] = kbdpc[VK_MWU] = kbdpc[VK_MWD] = 0;
  271.    if ((conf.fullscr || conf.lockmouse) && !nomouse)
  272.    {
  273.       unsigned cl1, cl2;
  274.       cl1 = unsigned(abs(msx - msx_prev)) * ay_reset_t / conf.frame;
  275.       cl2 = unsigned(abs(msx - msx_prev));
  276.       ay_x0 += int(cl2-cl1)*sign_pm(msx - msx_prev);
  277.       cl1 = unsigned(abs(msy - msy_prev)) * ay_reset_t / conf.frame;
  278.       cl2 = unsigned(abs(msy - msy_prev));
  279.       ay_y0 += int(cl2-cl1)*sign_pm(msy - msy_prev);
  280.       ay_reset_t = 0;
  281.  
  282. //      printf("%s\n", __FUNCTION__);
  283.       DIMOUSESTATE md;
  284.       readmouse(&md);
  285.       if (conf.input.mouseswap)
  286.       {
  287.           unsigned char t = md.rgbButtons[0];
  288.           md.rgbButtons[0] = md.rgbButtons[1];
  289.           md.rgbButtons[1] = t;
  290.       }
  291.       msx = md.lX; msy = -md.lY;
  292.       if (conf.input.mousescale >= 0)
  293.       {
  294.           msx *= (1 << conf.input.mousescale);
  295.           msy *= (1 << conf.input.mousescale);
  296.       }
  297.       else
  298.       {
  299.           msx /= (1 << -conf.input.mousescale);
  300.           msy /= (1 << -conf.input.mousescale);
  301.       }
  302.  
  303.       if (md.rgbButtons[0])
  304.       {
  305.           mbuttons &= ~1;
  306.           kbdpc[VK_LMB] = 0x80;
  307.       }
  308.       if (md.rgbButtons[1])
  309.       {
  310.           mbuttons &= ~2;
  311.           kbdpc[VK_RMB] = 0x80;
  312.       }
  313.       if (md.rgbButtons[2])
  314.       {
  315.           mbuttons &= ~4;
  316.           kbdpc[VK_MMB] = 0x80;
  317.       }
  318.  
  319.       int wheel_delta = md.lZ - prev_wheel;
  320.       prev_wheel = md.lZ;
  321. //      if (wheel_delta < 0) kbdpc[VK_MWD] = 0x80;
  322. //      if (wheel_delta > 0) kbdpc[VK_MWU] = 0x80;
  323. //0.36.6 from 0.35b2
  324.       if (conf.input.mousewheel == MOUSE_WHEEL_KEYBOARD)
  325.       {
  326.          if (wheel_delta < 0)
  327.              kbdpc[VK_MWD] = 0x80;
  328.          if (wheel_delta > 0)
  329.              kbdpc[VK_MWU] = 0x80;
  330.       }
  331.  
  332.       if (conf.input.mousewheel == MOUSE_WHEEL_KEMPSTON)
  333.       {
  334.          if (wheel_delta < 0)
  335.              wheel += 0x10; //24.11.2021 Alone
  336.          if (wheel_delta > 0)
  337.              wheel -= 0x10; //24.11.2021 Alone
  338.          mbuttons = (mbuttons & 0x0F) + (wheel & 0xF0);
  339.       }
  340. //~
  341.    }
  342.  
  343.  
  344.    if (nokb)
  345.           memset(kbdpc, 0, 256); // Мышь и джойстик не очищаем
  346.    else
  347.    {
  348. //      GetKeyboardState(kbdpc);
  349. //thims zxevo_ps/2
  350.       static unsigned char kbdpc_prev[VK_MAX];
  351.       if (buffer_enabled&&(!dbgbreak))
  352.           memcpy(kbdpc_prev, kbdpc, sizeof(kbdpc));
  353.  
  354.       ReadKeyboard(kbdpc);
  355.  
  356.           // Исправление "залипания" CapsLock, CapsLock при однократном нажатии возвращает всегда 0x80, пока не будет нажат повторно
  357.       u8 cl = kbdpc[DIK_CAPSLOCK];
  358.       kbdpc[DIK_CAPSLOCK] ^= CapsLockState;
  359.       CapsLockState = cl;
  360.  
  361.  
  362.       if (buffer_enabled&&(!dbgbreak))//DimkaM fix
  363.       {
  364.           for (int i = 0; i < sizeof(kbdpc); i++)
  365.           {
  366.              if ((kbdpc[i] & 0x80) != (kbdpc_prev[i] & 0x80) && dik_scan[i])
  367.              {
  368.                 if (dik_scan[i] & 0x0100) input.buffer.Push(0xE0);
  369.                 if (kbdpc_prev[i] & 0x80) input.buffer.Push(0xF0);
  370.                 input.buffer.Push(dik_scan[i] & 0x00FF);
  371.              }
  372.           }
  373.       }
  374.  
  375.       if (lastkey)
  376.       {
  377. //[vv]          kbdpc[lastkey] = 0x80;
  378.       }
  379.    }
  380.    lastkey = process_msgs();
  381. /* [vv]
  382.    if (temp.win9x)
  383.    {
  384.       kbdpc[VK_LSHIFT]=kbdpcEX[0];
  385.       kbdpc[VK_RSHIFT]=kbdpcEX[1];
  386.       kbdpc[VK_LCONTROL]=kbdpcEX[2];
  387.       kbdpc[VK_RCONTROL]=kbdpcEX[3];
  388.       kbdpc[VK_LMENU]=kbdpcEX[4];
  389.       kbdpc[VK_RMENU]=kbdpcEX[5];
  390.    } //Dexus
  391. */
  392.  
  393.    return lastkey ? 1 : 0;
  394. }
  395.  
  396. void K_INPUT::aymouse_wr(unsigned char val)
  397. {
  398.     // reset by edge bit6: 1->0
  399.     if(ayR14 & ~val & 0x40)
  400.     {
  401.         ay_x0 = ay_y0 = 8;
  402.         ay_reset_t = cpu.t;
  403.     }
  404.     ayR14 = val;
  405. }
  406.  
  407. unsigned char K_INPUT::aymouse_rd()
  408. {
  409.    unsigned coord;
  410.    if (ayR14 & 0x40) {
  411.       unsigned cl1 = unsigned(abs(msy - msy_prev)) * ay_reset_t / conf.frame;
  412.       unsigned cl2 = unsigned(abs(msy - msy_prev)) * cpu.t / conf.frame;
  413.       coord = unsigned(ay_y0 + int(cl2-cl1)*sign_pm(msy - msy_prev));
  414.    } else {
  415.       unsigned cl1 = unsigned(abs(msx - msx_prev)) * ay_reset_t / conf.frame;
  416.       unsigned cl2 = unsigned(abs(msx - msx_prev)) * cpu.t / conf.frame;
  417.       coord = unsigned(ay_x0 + int(cl2-cl1)*sign_pm(msx - msx_prev));
  418.    }
  419. /*
  420.    int coord = (ayR14 & 0x40)?
  421.      ay_y0 + 0x100 * (msy - msy_prev) * (int)(cpu.t - ay_reset_t) / (int)conf.frame:
  422.      ay_x0 + 0x100 * (msx - msx_prev) * (int)(cpu.t - ay_reset_t) / (int)conf.frame;
  423. //   if ((coord & 0x0F)!=8 && !(ayR14 & 0x40)) printf("coord: %X, x0=%4d, frame_dx=%6d, dt=%d\n", (coord & 0x0F), ay_x0, msx-msx_prev, cpu.t-ay_reset_t);
  424. */
  425.    return 0xC0 | (coord & 0x0F) | u8(mbuttons << 4);
  426. }
  427.  
  428. unsigned char K_INPUT::kempston_mx()
  429. {
  430.    int x = (int(cpu.t)*msx + int(conf.frame - cpu.t)*msx_prev) / int(conf.frame);
  431.    return (unsigned char)x;
  432. }
  433.  
  434. unsigned char K_INPUT::kempston_my()
  435. {
  436.    int y = (int(cpu.t)*msy + int(conf.frame - cpu.t)*msy_prev) / int(conf.frame);
  437.    return (unsigned char)y;
  438. }
  439.  
  440. unsigned char K_INPUT::read(unsigned char scan)
  441. {
  442.    unsigned char res = 0xBF | (tape_bit() & 0x40);
  443.    kbdled &= scan;
  444.  
  445.    if (conf.atm.xt_kbd)
  446.        return input.atm51.read(scan, res);
  447.  
  448.    for (int i = 0; i < 8; i++)
  449.    {
  450.       if (!(scan & (1<<i)))
  451.           res &= kbd[i];
  452.    }
  453.  
  454. /*
  455.    if(res != 0xFF)
  456.        __debugbreak();
  457. */
  458.  
  459.    return res;
  460. }
  461.  
  462. // read quorum additional keys (port 7E)
  463. u8 K_INPUT::read_quorum(u8 scan)
  464. {
  465.    u8 res = 0xFF;
  466.    kbdled &= scan;
  467.  
  468.    for (int i = 0; i < 8; i++)
  469.    {
  470.       if (!(scan & (1<<i)))
  471.           res &= kbd[8+i];
  472.    }
  473.  
  474.    return res;
  475. }
  476.  
  477. void K_INPUT::paste()
  478. {
  479.    free(textbuffer); textbuffer = nullptr;
  480.    textsize = textoffset = 0;
  481.    keymode = KM_DEFAULT;
  482.    if (!OpenClipboard(wnd)) return;
  483.    HANDLE hClip = GetClipboardData(CF_TEXT);
  484.    if (hClip) {
  485.       void *ptr = GlobalLock(hClip);
  486.       if (ptr) {
  487.          keymode = KM_PASTE_RELEASE; tdelay = 1;
  488.          textsize = unsigned(strlen((char*)ptr) + 1);
  489.          memcpy(textbuffer = (unsigned char*)malloc(textsize), ptr, textsize);
  490.          GlobalUnlock(hClip);
  491.       }
  492.    }
  493.    CloseClipboard();
  494. }
  495.  
  496. unsigned char ATM_KBD::read(unsigned char scan, unsigned char zxdata)
  497. {
  498.    unsigned char t;
  499.  
  500.    if (R7) {
  501.       if (R7 == 1) cmd = scan;
  502.       switch (cmd & 0x3F) {
  503.          case 1:
  504.          {
  505.             static const unsigned char ver[4] = { 6,0,1,0 };
  506.             R7 = 0; return ver[cmd >> 6];
  507.          }
  508.          case 7: clear(); R7 = 0; return 0xFF; // clear data buffer in mode0
  509.          case 8:
  510.             if (R7 == 2) { mode = scan; kR2 = 0; R7 = 0; return 0xFF; }
  511.             R7++; return 8;
  512.          case 9:
  513.             switch (cmd & 0xC0) {
  514.                case 0x00: t = kR1;
  515.                case 0x40: t = kR2;
  516.                case 0x80: t = kR3;
  517.                case 0xC0: t = kR4;
  518.             }
  519.             R7 = 0;
  520.             return t;
  521.          case 10:
  522.             kR3 |= 0x80; R7 = 0; return 0xFF;
  523.          case 11:
  524.             kR3 &= 0x7F; R7 = 0; return 0xFF;
  525. //         case 12: R7 = 0; return 0xFF; // enter pause mode
  526.          case 13:
  527.             // reset!
  528.             this->reset();
  529.             cpu.int_flags = cpu.ir_ = cpu.pc = 0; cpu.im = 0;
  530.             comp.p7FFD = comp.flags = 0;
  531.             set_atm_FF77(0,0);
  532.             set_banks();
  533.             break;
  534.          case 16:
  535.          case 18:
  536.          {
  537.             SYSTEMTIME time; GetLocalTime(&time);
  538.             R7 = 0;
  539.             if (cmd == 0x10) return (BYTE)time.wSecond;
  540.             if (cmd == 0x40) return (BYTE)time.wMinute;
  541.             if (cmd == 0x80) return (BYTE)time.wHour;
  542.             if (cmd == 0xC0) return (BYTE)time.wDay;
  543.             if (cmd == 0x12) return (BYTE)time.wDay;
  544.             if (cmd == 0x42) return (BYTE)time.wMonth;
  545.             if (cmd == 0x82) return (BYTE)(time.wYear % 100);
  546.             if (cmd == 0xC2) return (BYTE)(time.wYear / 100);
  547.          }
  548.          case 17: // set time
  549.          case 19: // set date
  550.             if (R7 == 2) R7 = 0; else R7++;
  551.             return 0xFF;
  552.       }
  553.       R7 = 0;
  554.       return 0xFF;
  555.    }
  556.  
  557.    if (scan == 0x55) { R7++; return 0xAA; }
  558.  
  559.    switch (mode & 3)
  560.    {
  561.       case 0:
  562.       {
  563.          unsigned char res = zxdata | 0x1F;
  564.          for (unsigned i = 0; i < 8; i++)
  565.             if (!(scan & (1 << i))) res &= zxkeys[i];
  566.          return res;
  567.       }
  568.       case 1: t = kR2; kR2 = 0; return t;
  569.       case 2:
  570.          switch (scan & 0xC0)
  571.          {
  572.             case 0x00: { t = kR2; kR2 = 0; return t; }
  573.             case 0x40: return kR3;
  574.             case 0x80: return kR4;
  575.             case 0xC0: return kR5;
  576.          }
  577.       case 3: t = lastscan; lastscan = 0; return t;
  578.    }
  579.    __assume(0);
  580.    return 0xFF;
  581. }
  582.  
  583. void ATM_KBD::processzx(unsigned scancode, unsigned char pressed)
  584. {
  585.    static const unsigned char L_4B6[] =
  586.    {
  587.       0x39, 0x31, 0x32, 0x33, 0x34, 0x35, 0x45, 0x44,
  588.       0x43, 0x42, 0x41, 0xE4, 0xE2, 0x49, 0x3B, 0x21,
  589.       0x22, 0x23, 0x24, 0x25, 0x55, 0x54, 0x53, 0x52,
  590.       0x51, 0xD5, 0xD4, 0x61, 0x88, 0x11, 0x12, 0x13,
  591.       0x14, 0x15, 0x65, 0x64, 0x63, 0x62, 0xD2, 0xD1,
  592.       0x91, 0x08, 0x92, 0x02, 0x03, 0x04, 0x05, 0x75,
  593.       0x74, 0x73, 0xF4, 0xF3, 0x85, 0x80, 0xF5, 0x3C,
  594.       0x71, 0x3A, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xC5,
  595.       0xC4, 0xC3, 0xC2, 0xC1, 0x00, 0x00, 0x3C, 0x4C,
  596.       0x3D, 0xE4, 0x3D, 0x35, 0x4B, 0xE3, 0x4A, 0x4D,
  597.       0x4B, 0x84, 0x49, 0x00, 0x00, 0x00, 0xE5, 0x94,
  598.       0x00, 0x00, 0x00
  599.    };
  600.  
  601.    scancode = (scancode & 0xFF) - 1;
  602.    if (scancode >= sizeof L_4B6)
  603.        return;
  604.  
  605.    unsigned char x = L_4B6[scancode];
  606.    if (x & 0x08) { if (pressed) zxkeys[0] &= ~1; else zxkeys[0] |= 1; }
  607.    if (x & 0x80) { if (pressed) zxkeys[7] &= ~2; else zxkeys[7] |= 2; }
  608.  
  609.    if (!(x & 7))
  610.        return;
  611.  
  612.    unsigned char data = u8(1 << ((x & 7) - 1));
  613.    x = (x >> 4) & 7;
  614.  
  615.    if (pressed)
  616.        zxkeys[x] &= ~data;
  617.    else
  618.        zxkeys[x] |= data;
  619. }
  620.  
  621. void ATM_KBD::setkey(unsigned scancode, unsigned char pressed)
  622. {
  623.    if (!(mode & 3)) processzx(scancode, pressed);
  624.    lastscan = (unsigned char)scancode;
  625.    if (!pressed) { lastscan |= 0x80; return; }
  626.  
  627.    kR3 &= 0x80; // keep rus/lat, clear alt,ctrl,shift, num/scroll/caps lock
  628.    if ((kbdpc[DIK_LSHIFT] | kbdpc[DIK_RSHIFT]) & 0x80) kR3 |= 1;
  629.    if ((kbdpc[DIK_LCONTROL] | kbdpc[DIK_RCONTROL]) & 0x80) kR3 |= 2;
  630.    if ((kbdpc[DIK_LMENU] | kbdpc[DIK_RMENU]) & 0x80) kR3 |= 4;
  631.    if (kbdpc[DIK_CAPITAL] & 1) kR3 |= 0x10;
  632.    if (kbdpc[DIK_NUMLOCK] & 1) kR3 |= 0x20;
  633.    if (kbdpc[DIK_SCROLL] & 1) kR3 |= 0x40;
  634.    kR4 = 0; if (kbdpc[DIK_RSHIFT] & 0x80) kR4++;
  635.  
  636.    static const unsigned char L_400[] =
  637.    {
  638.       0x1B, 0x00, 0x31, 0x00, 0x32, 0x00, 0x33, 0x00, 0x34, 0x00, 0x35, 0x00, 0x36, 0x00, 0x37, 0x00,
  639.       0x38, 0x00, 0x39, 0x00, 0x30, 0x00, 0x2D, 0x00, 0x3D, 0x00, 0x08, 0x00, 0x09, 0x00, 0x51, 0x00,
  640.       0x57, 0x00, 0x45, 0x00, 0x52, 0x00, 0x54, 0x00, 0x59, 0x00, 0x55, 0x00, 0x49, 0x00, 0x4F, 0x00,
  641.       0x50, 0x00, 0x5B, 0x00, 0x5D, 0x00, 0x0D, 0xC0, 0x00, 0x02, 0x41, 0x00, 0x53, 0x00, 0x44, 0x00,
  642.       0x46, 0x00, 0x47, 0x00, 0x48, 0x00, 0x4A, 0x00, 0x4B, 0x00, 0x4C, 0x00, 0x3B, 0x00, 0x27, 0x00,
  643.       0x60, 0x00, 0x00, 0x03, 0x5C, 0x00, 0x5A, 0x00, 0x58, 0x00, 0x43, 0x00, 0x56, 0x00, 0x42, 0x00,
  644.       0x4E, 0x00, 0x4D, 0x00, 0x2C, 0x00, 0x2E, 0x00, 0x2F, 0x40, 0x00, 0x03, 0xAA, 0x00, 0x00, 0x01,
  645.       0x20, 0x00, 0x00, 0x04, 0x61, 0x00, 0x62, 0x00, 0x63, 0x00, 0x64, 0x00, 0x65, 0x00, 0x66, 0x00,
  646.       0x67, 0x00, 0x68, 0x00, 0x69, 0x00, 0x6A, 0x00, 0x00, 0x08, 0x00, 0x0C, 0x37, 0x80, 0x38, 0x80,
  647.       0x39, 0x80, 0x2D, 0x80, 0x34, 0x80, 0x35, 0x80, 0x36, 0x80, 0x2B, 0x80, 0x31, 0x80, 0x32, 0x80,
  648.       0x33, 0x80, 0x30, 0x80, 0x2E, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x6B, 0x00, 0x6C, 0x00
  649.    };
  650.    unsigned index = ((scancode & 0xFF) - 1)*2;
  651.    if (index >= sizeof(L_400)) return;
  652.    kR1 = kR2; kR2 = L_400[index];
  653.    kR5 = L_400[index+1];
  654.  
  655.    if ((kR5 & 0x30) == 0x30) zxdata[0] = zxdata[1] = 0xFFFFFFFF;
  656.    static const unsigned char L_511[] = { 0x76, 0x70, 0x74, 0xAD, 0x72, 0xB5, 0x73, 0xAB, 0x77, 0x71, 0x75, 0x78, 0x79 };
  657.    if ((scancode & 0x100) && (kR5 & 0x40)) kR2 |= 0x80;
  658.    if (kR5 & 0x80) {
  659.       if (scancode & 0x100) kR2 = L_511[(scancode & 0xFF) - 0x47];
  660.       else kR2 |= 0x80;
  661.    }
  662.    if (kR5 & 0x0C) kR5 = 0;
  663. }
  664.  
  665. void ATM_KBD::clear()
  666. {
  667.    zxdata[0] = zxdata[1] = 0xFFFFFFFF;
  668. }
  669.  
  670. void ATM_KBD::reset()
  671. {
  672.    kR1 = kR2 = mode = lastscan = R7 = 0;
  673.    clear();
  674. }
  675.