[原创] 给NES模拟器增加USB手柄的支持

sjtitr   2014-8-30 12:38 楼主
给NES模拟器增加USB手柄的支持

参与HELPER2416开发板助学计划

上次提到了把NES放到HELPER2416上来跑,可是还不能控制,所以今天加个补丁篇——增加USB手柄的支持


由于我也才疏学浅,所以只是把手柄信息读出来就好,关于Linux输入设备相关的知识我也还需要更多学习才行。


就今天的目标:第一,读USB手柄的输入信息,第二:把信息整合到NES模拟器中。


实现第一个目标——我尝试了一下,手柄接到开发板上,会在/dev/input/下产生相应的event文件,我这里出现了event2,所以我只要读它就好:
  1. static DWORD my_pad1 = 0;
  2. void *thread_joy_listen(void *arg)

  3. {
  4.    int keys_fd;
  5.    char ret[2];
  6.    struct input_event t;

  7.    //keys_fd = open ("/dev/input/event2", O_RDONLY|O_NONBLOCK);
  8.    keys_fd = open ("/dev/input/event2", O_RDONLY);
  9.    if (keys_fd <= 0)
  10.      {
  11.        printf ("open /dev/input/event2 device error!\n");
  12.        return 0;
  13.      }

  14.    while (1)
  15.      {
  16.        if (read (keys_fd, &t, sizeof (t)) == sizeof (t))
  17.          {
  18.            switch(t.type)
  19.            {
  20.              case EV_ABS:
  21.                printf("EV_ABS - code 0x%02X, value 0x%02X\n", t.code, t.value);
  22.                switch(t.code)
  23.                {
  24.                case 0:
  25.                    switch(t.value)
  26.                    {
  27.                    case 0x80:
  28.                        my_pad1 &= ~(PAD_JOY_LEFT|PAD_JOY_RIGHT);
  29.                        break;
  30.                    case 0x00:
  31.                        my_pad1 |= PAD_JOY_LEFT;
  32.                        break;
  33.                    case 0xff:
  34.                        my_pad1 |= PAD_JOY_RIGHT;
  35.                        break;
  36.                    default:
  37.                        break;
  38.                    }
  39.                    break;
  40.                case 1:
  41.                    switch(t.value)
  42.                    {
  43.                    case 0x80:
  44.                        my_pad1 &= ~(PAD_JOY_UP|PAD_JOY_DOWN);
  45.                        break;
  46.                    case 0x00:
  47.                        my_pad1 |= PAD_JOY_UP;
  48.                        break;
  49.                    case 0xff:
  50.                        my_pad1 |= PAD_JOY_DOWN;
  51.                        break;
  52.                    default:
  53.                        break;
  54.                    }
  55.                    break;
  56.                default:
  57.                    break;
  58.                }
  59.                break;
  60.              /*
  61.              case EV_MSC:
  62.                printf("EV_MSC - code 0x%02X, value 0x%02X\n", t.code,t.value);
  63.                if(t.code == 0x04)
  64.                {
  65.                    switch(t.value)
  66.                    {
  67.                    case 0x90001:
  68.                        my_pad1 ^= PAD_JOY_A;
  69.                        break;
  70.                    case 0x90002:
  71.                        my_pad1 ^= PAD_JOY_B;
  72.                        break;
  73.                    case 0x90003:
  74.                        my_pad1 ^= PAD_JOY_B;
  75.                        break;
  76.                    case 0x90004:
  77.                        my_pad1 ^= PAD_JOY_A;
  78.                        break;
  79.                    case 0x90009:
  80.                        my_pad1 ^= PAD_JOY_SELECT;
  81.                        break;
  82.                    case 0x9000c:
  83.                        my_pad1 ^= PAD_JOY_START;
  84.                        break;
  85.                    default:
  86.                        break;
  87.                    }
  88.                }
  89.                break;
  90.            */
  91.            case EV_KEY:
  92.                printf("EV_KEY - code 0x%02X, value 0x%02X\n", t.code,t.value);
  93.                switch(t.code)
  94.                {
  95.                case 0x120:
  96.                    if(t.value)
  97.                    {
  98.                        my_pad1 |= PAD_JOY_B;
  99.                    }
  100.                    else
  101.                    {
  102.                        my_pad1 &= ~PAD_JOY_B;
  103.                    }
  104.                    break;
  105.                case 0x121:
  106.                    if(t.value)
  107.                    {
  108.                        my_pad1 |= PAD_JOY_A;
  109.                    }
  110.                    else
  111.                    {
  112.                        my_pad1 &= ~PAD_JOY_A;
  113.                    }
  114.                    break;
  115.                case 0x122:
  116.                    if(t.value)
  117.                    {
  118.                        my_pad1 |= PAD_JOY_A;
  119.                    }
  120.                    else
  121.                    {
  122.                        my_pad1 &= ~PAD_JOY_A;
  123.                    }
  124.                    break;
  125.                case 0x123:
  126.                    if(t.value)
  127.                    {
  128.                        my_pad1 |= PAD_JOY_B;
  129.                    }
  130.                    else
  131.                    {
  132.                        my_pad1 &= ~PAD_JOY_B;
  133.                    }
  134.                    break;
  135.                case 0x128:
  136.                    if(t.value)
  137.                    {
  138.                        my_pad1 |= PAD_JOY_SELECT;
  139.                    }
  140.                    else
  141.                    {
  142.                        my_pad1 &= ~PAD_JOY_SELECT;
  143.                    }
  144.                    break;
  145.                case 0x12b:
  146.                    if(t.value)
  147.                    {
  148.                        my_pad1 |= PAD_JOY_START;
  149.                    }
  150.                    else
  151.                    {
  152.                        my_pad1 &= ~PAD_JOY_START;
  153.                    }
  154.                    break;
  155.                default:
  156.                    break;
  157.                }
  158.                break;
  159.              default:
  160.                printf("UNKNOWN - type 0x%02X, code 0x%02X, value 0x%02X\n", t.type, t.code, t.value);
  161.                break;
  162.            }
  163.          }
  164.      }
  165.    close (keys_fd);
  166.    return 0;
  167. }


进一步的,需要解释:这个函数明显是做了一个线程,专门用来监视手柄状态。我原本想尝试在NES线程中直接不阻塞的读取手柄,可是失败了,最后才想了这个旁门左道的方法。


然后在程序启动以后,直接启动这个线程开始监听手柄了……
  1.     int err;
  2.     pthread_t ntid;
  3.     err = pthread_create(&ntid, NULL, thread_joy_listen, NULL);


然后只要在NES的手柄状态函数中,进行正确的赋值就可以了。
  1. /* Get a joypad state */
  2. void InfoNES_PadState( DWORD *pdwPad1, DWORD *pdwPad2, DWORD *pdwSystem )
  3. {
  4.    *pdwPad1 = my_pad1;
  5. }


所以,这样,就可以用手柄玩FC游戏了。补充一点,我的手柄值都是我自己试出来的,所以当你使用这些代码,也需要考虑手柄值的对应是否正确。


附上文件:
mainwindow.zip (3.46 KB)
(下载次数: 31, 2014-8-30 12:37 上传)



论坛ID:sjtitr
提交时间:2014.08.30




回复评论 (2)

在QT下边,可以使用/dev/tty1来读键盘,这个是被QT4直接实别的设备!
点赞  2014-8-30 16:47
过来看看
点赞  2014-8-30 17:26
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复