public void RegisterMAMEMessages()
            {
                // Retrieve our handle (needed when registering to MAME)
                HandleOfListener = this.Handle;

                // Register MAME messages
                OM_MAME_START = WinMsgUtils.RegisterWindowMessage(WinMsgUtils.OM_MAME_START);
                if (OM_MAME_START == 0)
                {
                    throw new Exception("error");
                }
                OM_MAME_STOP = WinMsgUtils.RegisterWindowMessage(WinMsgUtils.OM_MAME_STOP);
                if (OM_MAME_STOP == 0)
                {
                    throw new Exception("error");
                }
                OM_MAME_UPDATE_START = WinMsgUtils.RegisterWindowMessage(WinMsgUtils.OM_MAME_UPDATE_STATE);
                if (OM_MAME_UPDATE_START == 0)
                {
                    throw new Exception("error");
                }
                OM_MAME_REGISTER_CLIENT = WinMsgUtils.RegisterWindowMessage(WinMsgUtils.OM_MAME_REGISTER_CLIENT);
                if (OM_MAME_REGISTER_CLIENT == 0)
                {
                    throw new Exception("error");
                }
                OM_MAME_UNREGISTER_CLIENT = WinMsgUtils.RegisterWindowMessage(WinMsgUtils.OM_MAME_UNREGISTER_CLIENT);
                if (OM_MAME_UNREGISTER_CLIENT == 0)
                {
                    throw new Exception("error");
                }
                OM_MAME_GET_ID_STRING = WinMsgUtils.RegisterWindowMessage(WinMsgUtils.OM_MAME_GET_ID_STRING);
                if (OM_MAME_GET_ID_STRING == 0)
                {
                    throw new Exception("error");
                }


                // see if MAME or supermodel is already running
                var otherwnd = WinMsgUtils.FindWindow(WinMsgUtils.OUTPUT_WINDOW_CLASS, WinMsgUtils.OUTPUT_WINDOW_NAME);

                // If not found, try to found supermodel by process names
                if (otherwnd == IntPtr.Zero)
                {
                    var procs = Process.GetProcessesByName("supermodel");
                    if (procs.Length > 0)
                    {
                        procs[0].Refresh();
                        otherwnd = procs[0].MainWindowHandle;
                        //otherwnd = FindWindowEx(otherwnd, IntPtr.Zero, OUTPUT_WINDOW_NAME, IntPtr.Zero);
                    }
                }
                if (otherwnd != IntPtr.Zero)
                {
                    Message msg = new Message();
                    msg.WParam = otherwnd;
                    msg.LParam = IntPtr.Zero;
                    HandleMAMEStart(msg);
                }
            }
            int HandleMAMEStart(Message msg)
            {
                HandleToMAMEWindow = msg.WParam;

                Reset_id_to_outname_cache();

                // register ourselves as a client
                WinMsgUtils.PostMessage(HandleToMAMEWindow, OM_MAME_REGISTER_CLIENT, HandleOfListener, (IntPtr)WinMsgUtils.CLIENT_ID);
                //WinMsgUtils.SendMessage(mame_target, om_mame_register_client, listener_hwnd, (IntPtr)WinMsgUtils.CLIENT_ID);

                // get the game name
                Map_id_to_outname(IntPtr.Zero);

                return(0);
            }
            string Map_id_to_outname(IntPtr id)
            {
                // see if we have an entry in our map
                if (MapIDToName.ContainsKey(id))
                {
                    return(MapIDToName[id]);
                }
                // no entry yet; we have to ask
                WinMsgUtils.SendMessage(HandleToMAMEWindow, OM_MAME_GET_ID_STRING, HandleOfListener, id);

                // now see if we have the entry in our map
                if (MapIDToName.ContainsKey(id))
                {
                    return(MapIDToName[id]);
                }
                // if not, use an empty string
                return("");
            }