11/* mupen64plus-input-raphnetraw
22 *
3- * Copyright (C) 2016 Raphael Assenat
3+ * Copyright (C) 2016-2017 Raphael Assenat
44 *
55 * An input plugin that lets the game under emulation communicate with
66 * the controllers directly using the direct controller communication
3434 */
3535
3636#include <stdio.h>
37+ #include <string.h>
3738#include "plugin_back.h"
3839#include "gcn64.h"
3940#include "gcn64lib.h"
@@ -83,6 +84,7 @@ struct rawChannel {
8384 struct adapter * adapter ;
8485 int chn ;
8586};
87+
8688/* Multiple adapters are supported, some are single player, others
8789 * two-player. As they are discovered during scan, their
8890 * channels (corresponding to physical controller ports) are added
@@ -100,7 +102,7 @@ int pb_init(pb_debugFunc debugFn)
100102 return 0 ;
101103}
102104
103- int pb_shutdown (void )
105+ static void pb_freeAllAdapters (void )
104106{
105107 int i ;
106108
@@ -109,14 +111,20 @@ int pb_shutdown(void)
109111 /* RomClosed() should have done this, but just
110112 in case it is not always called, do this again here. */
111113 gcn64lib_suspendPolling (g_adapters [i ].handle , 0 );
112-
113114 gcn64_closeDevice (g_adapters [i ].handle );
114115 }
115116 }
116117
117- gcn64_shutdown ();
118118 g_n_channels = 0 ;
119119 g_n_adapters = 0 ;
120+ memset (g_adapters , 0 , sizeof (g_adapters ));
121+ memset (g_channels , 0 , sizeof (g_channels ));
122+ }
123+
124+ int pb_shutdown (void )
125+ {
126+ pb_freeAllAdapters ();
127+ gcn64_shutdown ();
120128
121129 return 0 ;
122130}
@@ -132,24 +140,30 @@ int pb_scanControllers(void)
132140
133141 lctx = gcn64_allocListCtx ();
134142 if (!lctx ) {
135- DebugMessage (PB_MSG_ERROR , "Could not allocate gcn64 list context\n " );
143+ DebugMessage (PB_MSG_ERROR , "Could not allocate gcn64 list context" );
136144 return 0 ;
137145 }
138146
147+ /* This may be called many times in the plugin's lifetime. For instance, each
148+ * time a new game is selected from the PJ64 menu. Freeing previously found
149+ * adapters here and creating a new list makes it possible to disconnect/replace
150+ * USB adapters without having to restart PJ64. */
151+ pb_freeAllAdapters ();
152+
139153 /* Pass 1: Fill g_adapters[] with the adapters present on the system. */
140154 g_n_adapters = 0 ;
141155 adap = & g_adapters [g_n_adapters ];
142156 while (gcn64_listDevices (& adap -> inf , lctx )) {
143157
144158 adap -> handle = gcn64_openDevice (& adap -> inf );
145159 if (!adap -> handle ) {
146- DebugMessage (PB_MSG_ERROR , "Could not open gcn64 device serial '%ls'. Skipping it.\n " , adap -> inf .str_serial );
160+ DebugMessage (PB_MSG_ERROR , "Could not open gcn64 device serial '%ls'. Skipping it." , adap -> inf .str_serial );
147161 continue ;
148162 }
149163
150164 DebugMessage (PB_MSG_INFO , "Found USB device 0x%04x:0x%04x serial '%ls' name '%ls'" ,
151165 adap -> inf .usb_vid , adap -> inf .usb_pid , adap -> inf .str_serial , adap -> inf .str_prodname );
152- DebugMessage (PB_MSG_INFO , "Adapter supports %d raw channels " , adap -> inf .caps .n_raw_channels );
166+ DebugMessage (PB_MSG_INFO , "Adapter supports %d raw channel(s) " , adap -> inf .caps .n_raw_channels );
153167
154168 g_n_adapters ++ ;
155169 if (g_n_adapters >= MAX_ADAPTERS )
@@ -160,7 +174,7 @@ int pb_scanControllers(void)
160174 gcn64_freeListCtx (lctx );
161175
162176 /* Pass 2: Fill the g_channel[] array with the available raw channels.
163- * For instance, if there are adapter A, B and C (where A and C are single-player
177+ * For instance, if there are adapters A, B and C (where A and C are single-player
164178 * and B is dual-player), we get this:
165179 *
166180 * [0] = Adapter A, raw channel 0
@@ -355,12 +369,12 @@ static int pb_performIo(void)
355369static int pb_commandIsValid (int Control , unsigned char * Command )
356370{
357371 if (Control < 0 || Control >= g_n_channels ) {
358- DebugMessage (PB_MSG_WARNING , "pb_readController called with Control=%d\n " , Control );
372+ DebugMessage (PB_MSG_WARNING , "pb_readController called with Control=%d" , Control );
359373 return 0 ;
360374 }
361375
362376 if (!Command ) {
363- DebugMessage (PB_MSG_WARNING , "pb_readController called with NULL Command pointer\n " );
377+ DebugMessage (PB_MSG_WARNING , "pb_readController called with NULL Command pointer" );
364378 return 0 ;
365379 }
366380
@@ -381,7 +395,7 @@ static int pb_commandIsValid(int Control, unsigned char *Command)
381395 // against this condition...
382396 //
383397 if (Control == 2 && Command [2 ] > 0x03 ) {
384- DebugMessage (PB_MSG_WARNING , "Invalid controller command\n " );
398+ DebugMessage (PB_MSG_WARNING , "Invalid controller command" );
385399 return 0 ;
386400 }
387401
@@ -438,7 +452,7 @@ int pb_readController(int Control, unsigned char *Command)
438452 adap = channel -> adapter ;
439453
440454 if (adap -> n_ops >= MAX_OPS ) {
441- DebugMessage (PB_MSG_ERROR , "Too many io ops\n " );
455+ DebugMessage (PB_MSG_ERROR , "Too many io ops" );
442456 } else {
443457 biops = adap -> biops ;
444458
0 commit comments