From e8e20a7dbd709645de1a8397d15707e754fe7068 Mon Sep 17 00:00:00 2001 From: SindenLightgun <47393540+SindenLightgun@users.noreply.github.com> Date: Sat, 14 Sep 2019 23:54:40 +0100 Subject: [PATCH 1/8] Adding Guncon support for mouse based lightguns --- frontend/libretro.c | 92 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 91 insertions(+), 1 deletion(-) diff --git a/frontend/libretro.c b/frontend/libretro.c index 081f8ba..620cd17 100644 --- a/frontend/libretro.c +++ b/frontend/libretro.c @@ -571,6 +571,8 @@ static void update_controller_port_variable(unsigned port) in_type[port] = PSE_PAD_TYPE_ANALOGPAD; else if (strcmp(var.value, "negcon") == 0) in_type[port] = PSE_PAD_TYPE_NEGCON; + else if (strcmp(var.value, "guncon") == 0) + in_type[port] = PSE_PAD_TYPE_GUNCON; else if (strcmp(var.value, "none") == 0) in_type[port] = PSE_PAD_TYPE_NONE; // else 'default' case, do nothing @@ -1907,6 +1909,94 @@ void retro_run(void) } } + if (in_type[i] == PSE_PAD_TYPE_GUNCON) + { + //ToDo move across to: + //RETRO_DEVICE_ID_LIGHTGUN_SCREEN_X + //RETRO_DEVICE_ID_LIGHTGUN_SCREEN_Y + //RETRO_DEVICE_ID_LIGHTGUN_TRIGGER + //RETRO_DEVICE_ID_LIGHTGUN_RELOAD + //RETRO_DEVICE_ID_LIGHTGUN_AUX_A + //RETRO_DEVICE_ID_LIGHTGUN_AUX_B + //Though not sure these are hooked up properly on the Pi + + //ToDo + //Put the controller index back to i instead of hardcoding to 1 when the libretro overlay crash bug is fixed + //This is required for 2 player + + //GUNCON has 3 controls, Trigger,A,B which equal Circle,Start,Cross + + // Trigger + //input_state_cb(i, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_O) + //The 1 is hardcoded instead of i to prevent the overlay mouse button libretro crash bug + if (input_state_cb(1, RETRO_DEVICE_MOUSE, 0, RETRO_DEVICE_ID_MOUSE_LEFT)){ + in_keystate[i] |= (1 << DKEY_CIRCLE); + } + + // A + if (input_state_cb(1, RETRO_DEVICE_MOUSE, 0, RETRO_DEVICE_ID_MOUSE_RIGHT)){ + in_keystate[i] |= (1 << DKEY_START); + } + + // B + if (input_state_cb(1, RETRO_DEVICE_MOUSE, 0, RETRO_DEVICE_ID_MOUSE_MIDDLE)){ + in_keystate[i] |= (1 << DKEY_CROSS); + } + + //The 1 is hardcoded instead of i to prevent the overlay mouse button libretro crash bug + int gunx = input_state_cb(1, RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_X); + int guny = input_state_cb(1, RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_Y); + + //This adjustment process gives the user the ability to manually align the mouse up better + //with where the shots are in the emulator. + + //Percentage distance of screen to adjust + int GunconAdjustX = 0; + int GunconAdjustY = 0; + + //Used when out by a percentage + float GunconAdjustRatioX = 1; + float GunconAdjustRatioY = 1; + + struct retro_variable var; + var.value = NULL; + var.key = "pcsx_rearmed_gunconadjustx"; + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) || var.value) + { + GunconAdjustX = atoi(var.value); + } + + var.value = NULL; + var.key = "pcsx_rearmed_gunconadjusty"; + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) || var.value) + { + GunconAdjustY = atoi(var.value); + } + + + var.value = NULL; + var.key = "pcsx_rearmed_gunconadjustratiox"; + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) || var.value) + { + GunconAdjustRatioX = atof(var.value); + } + + + var.value = NULL; + var.key = "pcsx_rearmed_gunconadjustratioy"; + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) || var.value) + { + GunconAdjustRatioY = atof(var.value); + } + + //Mouse range is -32767 -> 32767 + //1% is about 655 + //Use the left analog stick field to store the absolute coordinates + in_analog_left[0][0] = (gunx*GunconAdjustRatioX) + (GunconAdjustX * 655); + in_analog_left[0][1] = (guny*GunconAdjustRatioY) + (GunconAdjustY * 655); + + + } if (in_type[i] == PSE_PAD_TYPE_NEGCON) { // Query digital inputs @@ -2011,7 +2101,7 @@ void retro_run(void) // > NeGcon L in_analog_left[i][1] = get_analog_button(ret, input_state_cb, i, RETRO_DEVICE_ID_JOYPAD_L); } - else + if (in_type[i] != PSE_PAD_TYPE_NEGCON && in_type[i] != PSE_PAD_TYPE_GUNCON) { // Query digital inputs for (j = 0; j < RETRO_PSX_MAP_LEN; j++) From 2e6a3b0ee60c654873ca836d3f18ba9f57880fb4 Mon Sep 17 00:00:00 2001 From: SindenLightgun <47393540+SindenLightgun@users.noreply.github.com> Date: Sat, 14 Sep 2019 23:57:30 +0100 Subject: [PATCH 2/8] Adding Guncon support for mouse based lightguns --- libpcsxcore/plugins.c | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/libpcsxcore/plugins.c b/libpcsxcore/plugins.c index af7ebed..67fe835 100644 --- a/libpcsxcore/plugins.c +++ b/libpcsxcore/plugins.c @@ -640,6 +640,48 @@ void _PADstartPoll(PadDataS *pad) { stdpar[5] = pad->rightJoyY; stdpar[6] = pad->leftJoyX; stdpar[7] = pad->leftJoyY; + memcpy(buf, stdpar, 8); + respSize = 8; + break; + case PSE_PAD_TYPE_GUNCON: // GUNCON - gun controller SLPH-00034 from Namco + stdpar[0] = 0x63; + stdpar[1] = 0x5a; + stdpar[2] = pad->buttonStatus & 0xff; + stdpar[3] = pad->buttonStatus >> 8; + + //This code assumes an X resolution of 256 and a Y resolution of 240 + int xres = 256; + int yres = 240; + + //The code wants an input range for x and y of 0-1023 we passed in -32767 -> 32767 + int absX = (pad->absoluteX / 64) + 512; + int absY = (pad->absoluteY / 64) + 512; + + //Keep within limits + if (absX > 1023) absX = 1023; + if (absX < 0) absX = 0; + if (absY > 1023) absY = 1023; + if (absY < 0) absY = 0; + + stdpar[4] = 0x5a - (xres - 256) / 3 + (((xres - 256) / 3 + 356) * absX >> 10); + stdpar[5] = (0x5a - (xres - 256) / 3 + (((xres - 256) / 3 + 356) * absX >> 10)) >> 8; + stdpar[6] = 0x20 + (yres * absY >> 10); + stdpar[7] = (0x20 + (yres * absY >> 10)) >> 8; + + //Offscreen - Point at the side of the screen so PSX thinks you are pointing offscreen + //Required as a mouse can't be offscreen + //Coordinates X=0001h, Y=000Ah indicates "no light" + //This will mean you cannot shoot the very each of the screen + //ToDo read offscreen range from settings if useful to change + int OffscreenRange = 2; + if (absX < (OffscreenRange) || absX > (1023 - OffscreenRange) || absY < (OffscreenRange) || absY > (1023 - OffscreenRange)) + { + stdpar[4] = 0x01; + stdpar[5] = 0x00; + stdpar[6] = 0x0A; + stdpar[7] = 0x00; + } + memcpy(buf, stdpar, 8); respSize = 8; break; From 060544d078e63e299a36a846d3967db197de04a0 Mon Sep 17 00:00:00 2001 From: SindenLightgun <47393540+SindenLightgun@users.noreply.github.com> Date: Sat, 14 Sep 2019 23:59:29 +0100 Subject: [PATCH 3/8] Adding Guncon support for mouse based lightguns --- frontend/plugin.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/frontend/plugin.c b/frontend/plugin.c index 1fcd7be..30b0e08 100644 --- a/frontend/plugin.c +++ b/frontend/plugin.c @@ -58,12 +58,15 @@ static long PADreadPort1(PadDataS *pad) { else pad->portMultitap = 0; - if (in_type[pad_index] == PSE_PAD_TYPE_ANALOGJOY || in_type[pad_index] == PSE_PAD_TYPE_ANALOGPAD || in_type[pad_index] == PSE_PAD_TYPE_NEGCON) + if (in_type[pad_index] == PSE_PAD_TYPE_ANALOGJOY || in_type[pad_index] == PSE_PAD_TYPE_ANALOGPAD || in_type[pad_index] == PSE_PAD_TYPE_NEGCON || in_type[pad_index] == PSE_PAD_TYPE_GUNCON) { pad->leftJoyX = in_analog_left[pad_index][0]; pad->leftJoyY = in_analog_left[pad_index][1]; pad->rightJoyX = in_analog_right[pad_index][0]; pad->rightJoyY = in_analog_right[pad_index][1]; + + pad->absoluteX = in_analog_left[pad_index][0]; + pad->absoluteY = in_analog_left[pad_index][1]; } return 0; } @@ -78,12 +81,15 @@ static long PADreadPort2(PadDataS *pad) { else pad->portMultitap = 0; - if (in_type[pad_index] == PSE_PAD_TYPE_ANALOGJOY || in_type[pad_index] == PSE_PAD_TYPE_ANALOGPAD || in_type[pad_index] == PSE_PAD_TYPE_NEGCON) + if (in_type[pad_index] == PSE_PAD_TYPE_ANALOGJOY || in_type[pad_index] == PSE_PAD_TYPE_ANALOGPAD || in_type[pad_index] == PSE_PAD_TYPE_NEGCON || in_type[pad_index] == PSE_PAD_TYPE_GUNCON) { pad->leftJoyX = in_analog_left[pad_index][0]; pad->leftJoyY = in_analog_left[pad_index][1]; pad->rightJoyX = in_analog_right[pad_index][0]; pad->rightJoyY = in_analog_right[pad_index][1]; + + pad->absoluteX = in_analog_left[pad_index][0]; + pad->absoluteY = in_analog_left[pad_index][1]; } return 0; } From f3943713b53452d545fb58c9dee0c00dd0c2b6d7 Mon Sep 17 00:00:00 2001 From: SindenLightgun <47393540+SindenLightgun@users.noreply.github.com> Date: Sun, 15 Sep 2019 00:01:43 +0100 Subject: [PATCH 4/8] Adding Guncon support for mouse based lightguns --- plugins/dfinput/main.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/plugins/dfinput/main.c b/plugins/dfinput/main.c index 4204b86..af6b80b 100644 --- a/plugins/dfinput/main.c +++ b/plugins/dfinput/main.c @@ -1,5 +1,5 @@ /* - * (C) Gražvydas "notaz" Ignotas, 2011 + * (C) Gražvydas "notaz" Ignotas, 2011 * * This work is licensed under the terms of any of these licenses * (at your option): @@ -40,10 +40,11 @@ static int old_controller_type1 = -1, old_controller_type2 = -1; pad_init(); \ break; \ case PSE_PAD_TYPE_GUNCON: \ - PAD##n##_startPoll = PADstartPoll_guncon; \ - PAD##n##_poll = PADpoll_guncon; \ - guncon_init(); \ - break; \ + //Removed for new Guncon functionality, may have been required for very old touchscreen support + //PAD##n##_startPoll = PADstartPoll_guncon; \ + //PAD##n##_poll = PADpoll_guncon; \ + //guncon_init(); \ + //break; \ case PSE_PAD_TYPE_NEGCON: \ case PSE_PAD_TYPE_GUN: \ default: \ From 000655e4ea857d01a774d58689d95e6ddc67f0f8 Mon Sep 17 00:00:00 2001 From: SindenLightgun <47393540+SindenLightgun@users.noreply.github.com> Date: Sun, 15 Sep 2019 00:02:42 +0100 Subject: [PATCH 5/8] Adding Guncon support for mouse based lightguns --- frontend/libretro_core_options.h | 252 +++++++++++++++++++++++++++++++ 1 file changed, 252 insertions(+) diff --git a/frontend/libretro_core_options.h b/frontend/libretro_core_options.h index 6ea31e0..81a3ac2 100644 --- a/frontend/libretro_core_options.h +++ b/frontend/libretro_core_options.h @@ -106,6 +106,7 @@ struct retro_core_option_definition option_defs_us[] = { { "analog", NULL }, { "dualshock", NULL }, { "negcon", NULL }, + { "guncon", NULL }, { "none", NULL }, { NULL, NULL }, }, @@ -120,6 +121,7 @@ struct retro_core_option_definition option_defs_us[] = { { "analog", NULL }, { "dualshock", NULL }, { "negcon", NULL }, + { "guncon", NULL }, { "none", NULL }, { NULL, NULL }, }, @@ -134,6 +136,7 @@ struct retro_core_option_definition option_defs_us[] = { { "analog", NULL }, { "dualshock", NULL }, { "negcon", NULL }, + { "guncon", NULL }, { "none", NULL }, { NULL, NULL }, }, @@ -148,6 +151,7 @@ struct retro_core_option_definition option_defs_us[] = { { "analog", NULL }, { "dualshock", NULL }, { "negcon", NULL }, + { "guncon", NULL }, { "none", NULL }, { NULL, NULL }, }, @@ -162,6 +166,7 @@ struct retro_core_option_definition option_defs_us[] = { { "analog", NULL }, { "dualshock", NULL }, { "negcon", NULL }, + { "guncon", NULL }, { "none", NULL }, { NULL, NULL }, }, @@ -175,6 +180,7 @@ struct retro_core_option_definition option_defs_us[] = { { "analog", NULL }, { "dualshock", NULL }, { "negcon", NULL }, + { "guncon", NULL }, { "none", NULL }, { NULL, NULL }, }, @@ -188,6 +194,7 @@ struct retro_core_option_definition option_defs_us[] = { { "analog", NULL }, { "dualshock", NULL }, { "negcon", NULL }, + { "guncon", NULL }, { "none", NULL }, { NULL, NULL }, }, @@ -201,6 +208,7 @@ struct retro_core_option_definition option_defs_us[] = { { "analog", NULL }, { "dualshock", NULL }, { "negcon", NULL }, + { "guncon", NULL }, { "none", NULL }, { NULL, NULL }, }, @@ -269,6 +277,250 @@ struct retro_core_option_definition option_defs_us[] = { }, "enabled", }, + { + "pcsx_rearmed_gunconadjustx", + "Guncon Adjust X", + "When using Guncon mode, you can override aim in emulator if shots misaligned, this applies an increment on the x axis.", + { + { "0", NULL }, + { "-25", NULL }, + { "-24", NULL }, + { "-23", NULL }, + { "-22", NULL }, + { "-21", NULL }, + { "-20", NULL }, + { "-19", NULL }, + { "-18", NULL }, + { "-17", NULL }, + { "-16", NULL }, + { "-15", NULL }, + { "-14", NULL }, + { "-13", NULL }, + { "-12", NULL }, + { "-11", NULL }, + { "-10", NULL }, + { "-09", NULL }, + { "-08", NULL }, + { "-07", NULL }, + { "-06", NULL }, + { "-05", NULL }, + { "-04", NULL }, + { "-03", NULL }, + { "-02", NULL }, + { "-01", NULL }, + { "00", NULL }, + { "01", NULL }, + { "02", NULL }, + { "03", NULL }, + { "04", NULL }, + { "05", NULL }, + { "06", NULL }, + { "07", NULL }, + { "08", NULL }, + { "09", NULL }, + { "10", NULL }, + { "11", NULL }, + { "12", NULL }, + { "13", NULL }, + { "14", NULL }, + { "15", NULL }, + { "16", NULL }, + { "17", NULL }, + { "18", NULL }, + { "19", NULL }, + { "20", NULL }, + { "21", NULL }, + { "22", NULL }, + { "23", NULL }, + { "24", NULL }, + { "25", NULL }, + { NULL, NULL }, + }, + "0", + }, + { + "pcsx_rearmed_gunconadjusty", + "Guncon Adjust Y", + "When using Guncon mode, you can override aim in emulator if shots misaligned, this applies an increment on the y axis.", + { + { "0", NULL }, + { "-25", NULL }, + { "-24", NULL }, + { "-23", NULL }, + { "-22", NULL }, + { "-21", NULL }, + { "-20", NULL }, + { "-19", NULL }, + { "-18", NULL }, + { "-17", NULL }, + { "-16", NULL }, + { "-15", NULL }, + { "-14", NULL }, + { "-13", NULL }, + { "-12", NULL }, + { "-11", NULL }, + { "-10", NULL }, + { "-09", NULL }, + { "-08", NULL }, + { "-07", NULL }, + { "-06", NULL }, + { "-05", NULL }, + { "-04", NULL }, + { "-03", NULL }, + { "-02", NULL }, + { "-01", NULL }, + { "00", NULL }, + { "01", NULL }, + { "02", NULL }, + { "03", NULL }, + { "04", NULL }, + { "05", NULL }, + { "06", NULL }, + { "07", NULL }, + { "08", NULL }, + { "09", NULL }, + { "10", NULL }, + { "11", NULL }, + { "12", NULL }, + { "13", NULL }, + { "14", NULL }, + { "15", NULL }, + { "16", NULL }, + { "17", NULL }, + { "18", NULL }, + { "19", NULL }, + { "20", NULL }, + { "21", NULL }, + { "22", NULL }, + { "23", NULL }, + { "24", NULL }, + { "25", NULL }, + { NULL, NULL }, + }, + "0", + }, + { + "pcsx_rearmed_gunconadjustratiox", + "Guncon Adjust Ratio X", + "When using Guncon mode, you can override aim in emulator if shots misaligned, this applies a ratio on the x axis.", + { + { "1", NULL }, + { "0.75", NULL }, + { "0.76", NULL }, + { "0.77", NULL }, + { "0.78", NULL }, + { "0.79", NULL }, + { "0.80", NULL }, + { "0.81", NULL }, + { "0.82", NULL }, + { "0.83", NULL }, + { "0.84", NULL }, + { "0.85", NULL }, + { "0.86", NULL }, + { "0.87", NULL }, + { "0.88", NULL }, + { "0.89", NULL }, + { "0.90", NULL }, + { "0.91", NULL }, + { "0.92", NULL }, + { "0.93", NULL }, + { "0.94", NULL }, + { "0.95", NULL }, + { "0.96", NULL }, + { "0.97", NULL }, + { "0.98", NULL }, + { "0.99", NULL }, + { "1.00", NULL }, + { "1.01", NULL }, + { "1.02", NULL }, + { "1.03", NULL }, + { "1.04", NULL }, + { "1.05", NULL }, + { "1.06", NULL }, + { "1.07", NULL }, + { "1.08", NULL }, + { "1.09", NULL }, + { "1.10", NULL }, + { "1.11", NULL }, + { "1.12", NULL }, + { "1.13", NULL }, + { "1.14", NULL }, + { "1.15", NULL }, + { "1.16", NULL }, + { "1.17", NULL }, + { "1.18", NULL }, + { "1.19", NULL }, + { "1.20", NULL }, + { "1.21", NULL }, + { "1.22", NULL }, + { "1.23", NULL }, + { "1.24", NULL }, + { "1.25", NULL }, + { NULL, NULL }, + }, + "1", + }, + { + "pcsx_rearmed_gunconadjustratioy", + "Guncon Adjust Ratio Y", + "When using Guncon mode, you can override aim in emulator if shots misaligned, this applies a ratio on the y axis.", + { + { "1", NULL }, + { "0.75", NULL }, + { "0.76", NULL }, + { "0.77", NULL }, + { "0.78", NULL }, + { "0.79", NULL }, + { "0.80", NULL }, + { "0.81", NULL }, + { "0.82", NULL }, + { "0.83", NULL }, + { "0.84", NULL }, + { "0.85", NULL }, + { "0.86", NULL }, + { "0.87", NULL }, + { "0.88", NULL }, + { "0.89", NULL }, + { "0.90", NULL }, + { "0.91", NULL }, + { "0.92", NULL }, + { "0.93", NULL }, + { "0.94", NULL }, + { "0.95", NULL }, + { "0.96", NULL }, + { "0.97", NULL }, + { "0.98", NULL }, + { "0.99", NULL }, + { "1.00", NULL }, + { "1.01", NULL }, + { "1.02", NULL }, + { "1.03", NULL }, + { "1.04", NULL }, + { "1.05", NULL }, + { "1.06", NULL }, + { "1.07", NULL }, + { "1.08", NULL }, + { "1.09", NULL }, + { "1.10", NULL }, + { "1.11", NULL }, + { "1.12", NULL }, + { "1.13", NULL }, + { "1.14", NULL }, + { "1.15", NULL }, + { "1.16", NULL }, + { "1.17", NULL }, + { "1.18", NULL }, + { "1.19", NULL }, + { "1.20", NULL }, + { "1.21", NULL }, + { "1.22", NULL }, + { "1.23", NULL }, + { "1.24", NULL }, + { "1.25", NULL }, + { NULL, NULL }, + }, + "1", + }, { "pcsx_rearmed_dithering", "Enable Dithering", From 6190810ae9af3fd5f5030b4ffc05e861aa1f0769 Mon Sep 17 00:00:00 2001 From: SindenLightgun <47393540+SindenLightgun@users.noreply.github.com> Date: Sun, 15 Sep 2019 00:03:36 +0100 Subject: [PATCH 6/8] Update psemu_plugin_defs.h --- include/psemu_plugin_defs.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/include/psemu_plugin_defs.h b/include/psemu_plugin_defs.h index 6fc59b7..ce577b4 100644 --- a/include/psemu_plugin_defs.h +++ b/include/psemu_plugin_defs.h @@ -219,6 +219,9 @@ typedef struct //configuration mode Request 0x43 int configMode; unsigned char reserved[87]; + + //Lightgun values + int absoluteX,absoluteY; } PadDataS; From f1fcf5ee6b340b4945242c7ee2933e764edc90ad Mon Sep 17 00:00:00 2001 From: SindenLightgun <47393540+SindenLightgun@users.noreply.github.com> Date: Sun, 15 Sep 2019 00:06:20 +0100 Subject: [PATCH 7/8] Adding Guncon support for mouse based lightguns --- include/psemu_plugin_defs.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/psemu_plugin_defs.h b/include/psemu_plugin_defs.h index ce577b4..545cfca 100644 --- a/include/psemu_plugin_defs.h +++ b/include/psemu_plugin_defs.h @@ -220,7 +220,7 @@ typedef struct int configMode; unsigned char reserved[87]; - //Lightgun values + //Lightgun values int absoluteX,absoluteY; } PadDataS; From 03fc8e9043246716a36a152750c9c69cce301d73 Mon Sep 17 00:00:00 2001 From: SindenLightgun <47393540+SindenLightgun@users.noreply.github.com> Date: Sun, 15 Sep 2019 00:11:53 +0100 Subject: [PATCH 8/8] Adding Guncon support for mouse based lightguns --- frontend/libretro.c | 1 - 1 file changed, 1 deletion(-) diff --git a/frontend/libretro.c b/frontend/libretro.c index 620cd17..929477f 100644 --- a/frontend/libretro.c +++ b/frontend/libretro.c @@ -1927,7 +1927,6 @@ void retro_run(void) //GUNCON has 3 controls, Trigger,A,B which equal Circle,Start,Cross // Trigger - //input_state_cb(i, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_O) //The 1 is hardcoded instead of i to prevent the overlay mouse button libretro crash bug if (input_state_cb(1, RETRO_DEVICE_MOUSE, 0, RETRO_DEVICE_ID_MOUSE_LEFT)){ in_keystate[i] |= (1 << DKEY_CIRCLE);