pop'n beMouse compatibility
This commit is contained in:
Binary file not shown.
@@ -2,9 +2,12 @@
|
||||
#Persistent
|
||||
#include AHKHID.ahk
|
||||
|
||||
hArd := HID_Open("1ccf","4148")
|
||||
MsgBox Sorry, this script is currently broken (I now need to get it to send a proper feature report instead of an output report)
|
||||
ExitApp
|
||||
|
||||
hArd := HID_Open("1ccf","1000")
|
||||
while (hLED = -1) {
|
||||
hArd := HID_Open("1ccf","4148")
|
||||
hArd := HID_Open("1ccf","1000")
|
||||
Sleep, 5000
|
||||
}
|
||||
if 0 < 1 ; The left side of a non-expression if-statement is always the name of a variable.
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
# Ultimate Pop'n Controller
|
||||
|
||||
USB HID controller with 17 inputs (9 buttons, coin, test, reset, service), 20 outputs (18 lights, coin blocker, coin counter), 12-key matrix numpad, high polling rate, custom dll for full cabinet compatibility, and nice programmable features.
|
||||
USB HID controller with 17 inputs (9 buttons, coin, test, reset, service), 20 named outputs (18 lights, coin blocker, coin counter), 4 features (dip switches), 12-key matrix numpad, high polling rate, custom dll for full cabinet compatibility, Pop'n beMouse and Lively native compatibility, and nice programmable features.
|
||||
|
||||
The goal was to replace the official IO Board from my pop'n cabinet with a DIY controller instead, for stability reasons (Konami IO boards are prone to failure, most Pop'n Music cabinets in the wild have broken lamps...) but also for QoL improvements (this allows me to use my panel system-wide and not only in-game, which means I can control a multiboot menu, play with emulators etc..).
|
||||
|
||||
@@ -10,10 +10,14 @@ In combination with the PN5180-cardio project, the whole IO from a Pop'n Music c
|
||||
|
||||
# Leonardo version
|
||||
|
||||
Because I loved the ModeSwitch feature, I adapted the code so it could compile for Leonardo as well. Due to lack of gpio, in this case there's only 11 buttons and 9 lights, no keypad support, and reactive mode won't include AC light simulation (there's no side or top lamps, duh).
|
||||
This code was originally written for Arduino Due but is also compatible with Leonardo without any change required.
|
||||
|
||||
Due to lack of gpio, in this case there's only 11 buttons and 9 lights, no keypad support, and reactive mode won't include AC light simulation (there's no side or top lamps, but you might want to have a look at the ambilight branch for ws2812b side/top lamps).
|
||||
|
||||
I'm also taking advantage of the Leonardo EEPROM. On manually switching, the resulting lightmode is stored in the EEPROM so that it persists on controller disconnect/reconnect.
|
||||
|
||||
You only need to select "Leonardo" as your board type in Arduino IDE before flashing.
|
||||
|
||||
# Demo
|
||||
|
||||
https://www.instagram.com/p/CKE9HCQFCYM/
|
||||
@@ -45,9 +49,9 @@ The keypad code requires the Keypad library by Mark Stanley and Alexander Brevig
|
||||
|
||||
## I/O
|
||||
|
||||
This controller has 13 buttons (9 buttons + coin + service + reset + test), 4 dip-switches (only DIP4 is used in cabinets to select between 15 or 31kHz monitor resolution on boot), 8 lights (9 buttons + 5 top neon + 4 side pillar), 2 coin outputs (coin blocker, coin counter).
|
||||
This controller has 13 buttons (9 buttons + coin + service + reset + test), 4 dip-switches (only DIP4 is used in cabinets to select between 15 or 31kHz monitor resolution on boot), 18 lights (9 buttons + 5 top neon + 4 side pillar), 2 coin outputs (coin blocker, coin counter).
|
||||
|
||||
It also has 7 pins for the 12-key numpad, following the original cabinet pinout. It is recognized as a separate keyboard, and it is mapped to the keyboard toprow rather than the numpad (due to lack of stability when sending the numlock command to the BemaniPC).
|
||||
It also has 7 pins for the 12-key numpad, following the original cabinet pinout. It is recognized as a separate keyboard, and it is mapped to the keyboard toprow rather than the numpad (due to lack of stability when sending the numlock command to the BemaniPC).
|
||||
|
||||
The 00 key is mapped to comma (for direct compatibility with spicetools) and the originally unused bottom right key is mapped to the default card scan key.
|
||||
|
||||
@@ -55,10 +59,14 @@ It also has a cool light animation on boot which you can easily adapt to your li
|
||||
|
||||
## ezusb driver
|
||||
|
||||
The I/O is HID so it can be mapped with the usual IO emulation tools, but it can also be used without emulation, just like an official IOBoard, provided you replace the original `ezusb.dll` file with the one from this repo.
|
||||
The I/O is HID so it can be mapped with the usual IO emulation tools, and even has named outputs for ease of use, but it can also be used just like an official IOBoard, provided you replace the original `ezusb.dll` file with the one from this repo.
|
||||
|
||||
This way the firmware is fully compatible with anything that works on an official cabinet (PopnForwarder (a bit silly but why not :D), DJMame, ezPSXe pad plugin...)
|
||||
|
||||
## pop'n beMouse
|
||||
|
||||
The controller will enumerate in a way that is directly compatible with the old Pop'n beMouse software (it also directly works with Pop'n Lively).
|
||||
|
||||
## Light modes
|
||||
|
||||
There are 5 different modes :
|
||||
|
||||
Binary file not shown.
Binary file not shown.
+20
-19
@@ -56,7 +56,7 @@ BOOLEAN get_device_path(wchar_t *lPath)
|
||||
continue;
|
||||
|
||||
/* check if the device contains our wanted vid/pid */
|
||||
if ( wcsstr( pspdidd->DevicePath, L"vid_1ccf&pid_4148&mi_02" ) == NULL )
|
||||
if ( wcsstr( pspdidd->DevicePath, L"vid_1ccf&pid_1000&mi_02" ) == NULL )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
@@ -140,32 +140,32 @@ static int controller_init(){
|
||||
* @return 0 on success, -1 on error
|
||||
*/
|
||||
static int controller_read_buttons(uint32_t *pad_bits){
|
||||
DWORD uint8_tsRead = 0;
|
||||
uint8_t res[4];
|
||||
unsigned char buf[6]; // gamepad report length is 3 uint8_ts in firmware, doubled because NumInputBuffer is set to 2
|
||||
DWORD bytesRead = 0;
|
||||
uint8_t res[4];
|
||||
unsigned char buf[6]; // gamepad report length is 3 bytes in firmware, doubled because NumInputBuffer is set to 2
|
||||
|
||||
buf[0] = 0x04; // gamepad report ID is 4 in firmware
|
||||
*pad_bits = 0;
|
||||
|
||||
ReadFile(g_hid_handle, buf, 6, &uint8_tsRead, NULL);
|
||||
// uint8_tsRead should either be 6 (if it successfully read 2 reports) or 3 (only one)
|
||||
if ( uint8_tsRead != 6 && uint8_tsRead != 3 )
|
||||
ReadFile(g_hid_handle, buf, 6, &bytesRead, NULL);
|
||||
// bytesRead should either be 6 (if it successfully read 2 reports) or 3 (only one)
|
||||
if ( bytesRead != 6 && bytesRead != 3 )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
printf("HID read error (got %u uint8_ts)\n",uint8_tsRead);
|
||||
printf("HID read error (got %u bytes)\n",bytesRead);
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* HID read ok, convert latest report uint8_ts to pop'n bitfield */
|
||||
/* HID read ok, convert latest report bytes to pop'n bitfield */
|
||||
res[3] = 0;
|
||||
res[2] = (buf[uint8_tsRead-1]<<3 | buf[uint8_tsRead-1]) & 0x41;
|
||||
res[1] = buf[uint8_tsRead-2];
|
||||
res[2] = (buf[bytesRead-1]<<3 | buf[bytesRead-1]) & 0x41;
|
||||
res[1] = buf[bytesRead-2];
|
||||
res[0] = 0;
|
||||
buf[uint8_tsRead-1] >>= 1;
|
||||
if ( buf[uint8_tsRead-1]&1 ) res[0] |= 0x80;
|
||||
buf[uint8_tsRead-1] >>= 1;
|
||||
if ( buf[uint8_tsRead-1]&1 ) res[0] |= 0x40;
|
||||
buf[bytesRead-1] >>= 1;
|
||||
if ( buf[bytesRead-1]&1 ) res[0] |= 0x80;
|
||||
buf[bytesRead-1] >>= 1;
|
||||
if ( buf[bytesRead-1]&1 ) res[0] |= 0x40;
|
||||
*pad_bits = *(uint32_t *)res;
|
||||
|
||||
/* dip switches */
|
||||
@@ -177,7 +177,7 @@ static int controller_read_buttons(uint32_t *pad_bits){
|
||||
if (((i+1)%4)==0) printf(" ");
|
||||
}
|
||||
printf("\n");
|
||||
if (*pad_bits & 0x8000000) printf("31kHz mode\n");
|
||||
if (*pad_bits & 0x8000000) printf("31kHz mode\r\n");
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
@@ -303,7 +303,7 @@ __declspec(dllexport) int __cdecl usbSetExtIo(int i) {
|
||||
__declspec(dllexport) int __cdecl usbStart(int i) {
|
||||
if (controller_init() == -1)
|
||||
{
|
||||
printf("Could not init device.\n");
|
||||
printf("Could not init device.\r\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -312,7 +312,7 @@ __declspec(dllexport) int __cdecl usbStart(int i) {
|
||||
2);
|
||||
if (!hidres)
|
||||
{
|
||||
printf("error %d setnuminputbuff\n",GetLastError());
|
||||
printf("Error %d setnuminputbuff\r\n",GetLastError());
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -320,7 +320,7 @@ __declspec(dllexport) int __cdecl usbStart(int i) {
|
||||
uint8_t feat[2] = {0x06, 0x00};
|
||||
if (!HidD_GetFeature(g_hid_handle, &feat, 2))
|
||||
{
|
||||
printf("error %d getFeature\n",GetLastError());
|
||||
printf("Cannot read dipswitches (error %d)\r\n",GetLastError());
|
||||
};
|
||||
g_dip_state = feat[1];
|
||||
|
||||
@@ -368,3 +368,4 @@ BOOL APIENTRY DllMain( HMODULE hModule,
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -368,7 +368,7 @@ uint8_t STRING_ID_LED_Count = 9;
|
||||
#endif
|
||||
|
||||
const DeviceDescriptor PROGMEM USB_DeviceDescriptorIAD =
|
||||
D_DEVICE(0xEF,0x02,0x01,64,0x1ccf,0x4148,0x100,IMANUFACTURER,IPRODUCT,ISERIAL,1);
|
||||
D_DEVICE(0xEF,0x02,0x01,64,0x1ccf,0x1000,0x100,IMANUFACTURER,IPRODUCT,ISERIAL,1);
|
||||
|
||||
/* PluggableUSBModule IMPLEMENTATION */
|
||||
|
||||
|
||||
Reference in New Issue
Block a user