yoshisuga / MAME4iOS

Multiple Arcade Machine Emulator for iOS, iPadOS, tvOS, macOS (Catalyst)
Other
635 stars 103 forks source link

Mouse bug... #454

Open seleuco opened 4 months ago

seleuco commented 4 months ago

@ToddLa

Hi todd.

I have been updating the Android MAME port so that it works with the latest pc desktop version version

https://github.com/seleuco/MAME4droid-2024/tree/main

I started the development using your OSD modifications (libmame 250)since you have done a magnificent job and it has sense to start with.

When I implemented the mouse support I went crazy because you have a bug that makes the mouse seem to work but it is not really working it well.

Specifically, when mame invokes void ios_osd_interface::input_update(bool relative_reset) the relative_reset parameter indicates that this is when the relative data (the mouse) must be polled, therefore it must be passed to do the effective polling:

m_callbacks.input_poll(relative_reset,&g_input, sizeof(g_input));

....

   if(relative_reset) {
        for (int i = 0; i < MYOSD_NUM_MICE; i++) {
            input->mouse_status[i] = mouse_status[i];

            input->mouse_x[i] = mouse_x[i] * 512;
            input->mouse_y[i] = mouse_y[i] * 512;

            pthread_mutex_lock(&mouse_mutex);

            mouse_x[i] = 0;
            mouse_y[i] = 0;

            pthread_mutex_unlock(&mouse_mutex);
        }
    }

I hope this helps if you still maintain the iOS port, which is great :)

ToddLa commented 4 months ago

Thanks! I did not fully understand how MAME handles relative devices, I will update next time we do a release.

ToddLa commented 4 months ago

My MAME OSD, assumes the client will do all the rendering (on iOS we use Metal)

Did you do that on Android, or did you put back the option to render to a bitmap?

seleuco commented 4 months ago

Yeah. I know you do all the rendering on the client. At the moment I make a bitmap although later in the client I apply shaders and I support a lot of glsl shaders. In any case this approach has clear disadvantages with artwork of course.

I want to try to get bgfx running at some point, which would be better than reinventing the wheel but so far renderer has been fast developed and works fast and well.

I also wanted to respect MAME UI unlike you on iOS because on Android there are already great third-party frontends with which I integrate. I have tried to enhance the MAME UI with media scraping and including resources such as history data and mame info which authors has given permission to me. Also I made it touch enabled, so by default you have an experience very similar to the PC experience, which I like.

Ahhh. One important thing mame Devs have fixed discrete sound bug in a recent commit. Al least works fine on my arm64 build without numprocessors setted to one. That is important because improves performance in threaded rendering like the one on namco system 22 which run full speed on my device.

It is curious but my port has not any issue with sound. I have seen you have been struggling with sound issues on iOS devices. In fact, I'm running in a low latency path mode so buffering is setted to 2/3 frames and there is not any underun.

ToddLa commented 4 months ago

YES audio bug fixed! I have bang'd my head trying to work around that. Setting num-cpu to one killed me!

Thanks

ToddLa commented 4 months ago

Yea hires artwork looks great when you handle the render, and vector games can draw nice hires lines

ToddLa commented 2 months ago

FYI I did an update to my MAME fork to MAME 264....

I am looking at the mouse issue now, and have a question...

Wouldn't relative-reset make more sense like this....

for (int i = 0; i < MYOSD_NUM_MICE; i++) {
  input->mouse_status[i] = mouse_status[i];

  input->mouse_x[i] = mouse_x[i] * 512;
  input->mouse_y[i] = mouse_y[i] * 512;

  if(relative_reset) { 
    pthread_mutex_lock(&mouse_mutex);
    mouse_x[i] = 0;
    mouse_y[i] = 0;
    pthread_mutex_unlock(&mouse_mutex);
  }
}
ToddLa commented 2 months ago

I have never gotten the MAME "DOS" UX to use the mouse, maybe this change will fix it!!

Also the relative-reset flag was added relatively recently, thanks for letting me know about it!

seleuco commented 2 months ago

FYI I did an update to my MAME fork to MAME 264....

I am looking at the mouse issue now, and have a question...

Wouldn't relative-reset make more sense like this....

for (int i = 0; i < MYOSD_NUM_MICE; i++) {
  input->mouse_status[i] = mouse_status[i];

  input->mouse_x[i] = mouse_x[i] * 512;
  input->mouse_y[i] = mouse_y[i] * 512;

  if(relative_reset) { 
    pthread_mutex_lock(&mouse_mutex);
    mouse_x[i] = 0;
    mouse_y[i] = 0;
    pthread_mutex_unlock(&mouse_mutex);
  }
}

Empirically, it is working correctly for me.

If you look at https://github.com/mamedev/mame/blob/master/src/osd/modules/input/input_rawinput.cpp

at the poll interval, if the relative_reset is set, then they exchange the mouse data an set it to zero the member one

`

  virtual void poll(bool relative_reset) override
{
    rawinput_device::poll(relative_reset);
    if (relative_reset)
    {
        m_mouse.lX = std::exchange(m_x, 0);
        m_mouse.lY = std::exchange(m_y, 0);
        m_mouse.lV = std::exchange(m_v, 0);
        m_mouse.lH = std::exchange(m_h, 0);
    }
}

`

seleuco commented 2 months ago

I have never gotten the MAME "DOS" UX to use the mouse, maybe this change will fix it!!

Also the relative-reset flag was added relatively recently, thanks for letting me know about it!

Making the mouse to work correctly is more important than it seems because there are artworks that are clickable.. :)

For the mouse to work in the UI and in the artwork, mouse events must be injected directly. It doesn't work like it does with games.

look at here:

https://github.com/seleuco/MAME4droid-2024/blob/main/src/osd/myosd/myosdmain.cpp

` extern "C" void myosd_pushEvent(myosd_inputevent event) { if(osdInterface!= nullptr && osdInterface->isMachine() && osdInterface->target()!= nullptr) {

    switch(event.type) {
        case event.MYOSD_KEY_EVENT:
            osdInterface->machine().ui_input().push_char_event(osdInterface->target(), event.data.key_char);
            break;
        case event.MYOSD_MOUSE_MOVE_EVENT:
            osdInterface->machine().ui_input().push_mouse_move_event(osdInterface->target(), event.data.mouse_data.x, event.data.mouse_data.y);
            break;
        case event.MYOSD_MOUSE_BT1_DBLCLK:
            osdInterface->machine().ui_input().push_mouse_double_click_event(osdInterface->target(), event.data.mouse_data.x, event.data.mouse_data.y);
            break;
        case event.MYOSD_MOUSE_BT1_DOWN:
            osdInterface->machine().ui_input().push_mouse_down_event(osdInterface->target(), event.data.mouse_data.x, event.data.mouse_data.y);
            break;
        case event.MYOSD_MOUSE_BT1_UP:
            osdInterface->machine().ui_input().push_mouse_up_event(osdInterface->target(), event.data.mouse_data.x, event.data.mouse_data.y);
            break;
        case event.MYOSD_MOUSE_BT2_DOWN:
            osdInterface->machine().ui_input().push_mouse_rdown_event(osdInterface->target(), event.data.mouse_data.x, event.data.mouse_data.y);
            break;
        case event.MYOSD_MOUSE_BT2_UP:
            osdInterface->machine().ui_input().push_mouse_rup_event(osdInterface->target(), event.data.mouse_data.x, event.data.mouse_data.y);
            break;
        default:
            osd_printf_error("has unknown myosd event type (%u)\n",event.type);
    }

}

} `

and here:

https://github.com/seleuco/MAME4droid-2024/blob/main/src/osd/myosd/myosd-droid.cpp

` int myosd_droid_setMouseData(int i, int mouseAction, int button, float cx, float cy) {

if(mouseAction == com_seleuco_mame4droid_Emulator_MOUSE_MOVE)
{
    cur_x_mouse = MAX(0, MIN(cx + cur_x_mouse, myosd_droid_video_width));
    cur_y_mouse = MAX(0, MIN(cy + cur_y_mouse, myosd_droid_video_height));

    myosd_inputevent ev;
    ev.type = ev.MYOSD_MOUSE_MOVE_EVENT;
    ev.data.mouse_data.x = cur_x_mouse;
    ev.data.mouse_data.y = cur_y_mouse;
    myosd_pushEvent(ev);

    if(!myosd_droid_inMenu) {
        pthread_mutex_lock(&mouse_mutex);

        mouse_x[i] += cx;
        mouse_y[i] += cy;

        pthread_mutex_unlock(&mouse_mutex);
   }
}
else if(mouseAction == com_seleuco_mame4droid_Emulator_MOUSE_MOVE_POINTER)
{
    cur_x_mouse = cx;
    cur_y_mouse = cy;

    myosd_inputevent ev;
    ev.type = ev.MYOSD_MOUSE_MOVE_EVENT;
    ev.data.mouse_data.x = cur_x_mouse;
    ev.data.mouse_data.y = cur_y_mouse;
    myosd_pushEvent(ev);
}
else if(mouseAction == com_seleuco_mame4droid_Emulator_MOUSE_BTN_DOWN)
{
    myosd_inputevent ev;
    ev.data.mouse_data.x = cur_x_mouse;
    ev.data.mouse_data.y = cur_y_mouse;

    if(button==1) {

        ev.type = ev.MYOSD_MOUSE_BT1_DOWN;
        myosd_pushEvent(ev);

        static float last_click_x = 0;
        static float last_click_y = 0;
        static std::chrono::steady_clock::time_point last_click_time = std::chrono::steady_clock::time_point::min();

        auto double_click_speed = std::chrono::milliseconds(250);
        auto const click = std::chrono::steady_clock::now();

        int offsetX = 4;
        int offsetY = 4;
        if(cx != -1 && cy != -1) {
            offsetX = cx;
            offsetY = cy;
            double_click_speed = std::chrono::milliseconds(400);
        }

        if (click < (last_click_time + double_click_speed)
            && (cur_x_mouse >= (last_click_x - offsetX) && cur_x_mouse <= (last_click_x + offsetX))
            && (cur_y_mouse >= (last_click_y - offsetY) && cur_y_mouse <= (last_click_y + offsetY)))
        {
            last_click_time = std::chrono::time_point<std::chrono::steady_clock>::min();
            ev.type = ev.MYOSD_MOUSE_BT1_DBLCLK;
            myosd_pushEvent(ev);
            __android_log_print(ANDROID_LOG_DEBUG, "libMAME4droid.so", "MOUSEB PULSO BT1 DBLCLK!!!!");
        }
        else
        {
            last_click_time = click;
            last_click_x = cur_x_mouse;
            last_click_y = cur_y_mouse;
        }

        mouse_status[i] |= MYOSD_A;
        __android_log_print(ANDROID_LOG_DEBUG, "libMAME4droid.so", "MOUSEB PULSO BT1!");
    }
    else if(button == 2)
    {
        ev.type = ev.MYOSD_MOUSE_BT2_DOWN;
        myosd_pushEvent(ev);
        mouse_status[i] |= MYOSD_B;
    }
    else if(button == 3)
    {
        mouse_status[i] |= MYOSD_C;
    }
}
else if(mouseAction == com_seleuco_mame4droid_Emulator_MOUSE_BTN_UP)
{
    myosd_inputevent ev;
    ev.data.mouse_data.x = cur_x_mouse;
    ev.data.mouse_data.y = cur_y_mouse;

    if(button==1)
    {
        ev.type = ev.MYOSD_MOUSE_BT1_UP;
        myosd_pushEvent(ev);
        mouse_status[i] &= ~MYOSD_A;
    }
    else if(button==2)
    {
        ev.type = ev.MYOSD_MOUSE_BT2_UP;
        myosd_pushEvent(ev);
        mouse_status[i] &= ~MYOSD_B;
    }
    else if(button==3)
    {
        mouse_status[i] &= ~MYOSD_C;
    }
}

return 1;

} `

Also keyboard has to be inyected ....

Anyway i think that @cuavas has changed a lot of this in a recent commit because it has added some type of touch support. I will dig on it when they launch 0.265