diff --git a/Agents.md b/Agents.md
new file mode 100644
index 0000000..7a145ed
--- /dev/null
+++ b/Agents.md
@@ -0,0 +1,107 @@
+# SnapKey v1.2.9 Agents 自动化修改规范
+
+## 1. VAC Bypass 配置可调(config.cfg 可选项)
+
+### 目标
+
+* 允许**VAC绕过A/B**功能在`config.cfg`配置文件中保存其开关状态。
+* 允许**两个模式下所有Sleep延迟**范围可在配置文件调整(区分A/B模式)。
+
+### 配置文件示例(新增段落)
+
+```ini
+# VAC Bypass 配置
+vac_bypass_a = 1 # 1=启用 0=关闭
+vac_bypass_b = 0 # 1=启用 0=关闭
+
+# VAC Bypass 延迟设置(单位:毫秒)
+vac_a_min_delay = 15 # A模式最低 overlap 延迟
+vac_a_max_delay = 35 # A模式最大 overlap 延迟
+
+vac_b_min_delay = 5 # B模式最小释放-按下间隔
+vac_b_max_delay = 15 # B模式最大释放-按下间隔
+```
+
+* **默认值**见上。
+* **禁止负数、最大最小颠倒。**
+* 未设置时,按默认值初始化。
+
+---
+
+## 2. 延迟生成随机数机制升级
+
+### 目标
+
+* 所有 VAC 绕过相关的延迟逻辑全部替换为 C++11 标准 `std::mt19937`(Mersenne Twister)+ `std::chrono`。
+* 不允许使用 C 的 `rand()`,保证多线程/多实例下延迟分布均匀无碰撞。
+
+### 必须实现
+
+* 延迟取值每次都要走同一 `std::mt19937` 实例(优先全局静态),用 `std::random_device` 进行 seed。
+* **调用样例:**
+
+ ```cpp
+ static std::mt19937 rng(std::random_device{}());
+ std::uniform_int_distribution dist(min, max);
+ int delay = dist(rng);
+ std::this_thread::sleep_for(std::chrono::milliseconds(delay));
+ ```
+
+---
+
+## 3. VAC 绕过菜单状态和图标动态切换
+
+### 目标
+
+* **新增一个 icon\_vac\_bypass.ico(128x128)**
+
+ * 图案要求:
+
+ * 大号 VAC 字母(可参照 Valve Anti-Cheat 原色),下方画一个长水平箭头(建议 **→ 或 --**> 结构,强调“穿透/绕过”意象)
+ * 图标风格必须“和 icon.ico、icon\_off.ico 一致”,不可过于复杂,保证 16x16 到 128x128 兼容缩放。
+* **图标切换规则:**
+
+ * **SnapKey 启用**,且**任一 VAC bypass 功能启用**:显示 icon\_vac\_bypass.ico
+ * **SnapKey 禁用**(isLocked=true):只显示 icon\_off.ico(无论VAC选项)
+ * 其它情况仍为普通 icon.ico
+* 菜单栏**VAC bypass A/B 状态**同步菜单打钩与图标状态。
+
+---
+
+## 4. 稳定性与兼容性要求
+
+* 任何图标读取失败时,fallback 到 icon.ico,不允许图标状态丢失或崩溃。
+* 菜单状态与配置文件保持一致(修改菜单选项应自动写回 config.cfg,重启自动读取)。
+* 保持原有的托盘右键菜单逻辑和热键绑定管理不变。
+
+---
+
+## 5. agents.md 生成自动化流程推荐
+
+(适合 CI/CD 或脚本辅助开发环境)
+
+1. 检查 config.cfg 是否存在上述新段落。不存在则自动补全默认项。
+2. 替换所有 `Sleep(rand() % X)` 为 std::mt19937 + chrono 方案。
+3. 更新 Tray 菜单栏,VAC bypass A/B 绑定菜单、菜单项与 config 状态同步。
+4. 插入图标切换判定逻辑:任一绕过启用 && SnapKey 启用 → icon\_vac\_bypass.ico,否则按旧逻辑。
+5. 变更或菜单开关时自动写 config.cfg。
+6. 自动检测并加载 icon\_vac\_bypass.ico,找不到 fallback。
+7. 强制所有配置解析后做一次合法性检查(无效配置自动回落到默认)。
+8. 不影响原有 Group/Key 配置、版本信息、帮助菜单等其它业务。
+
+---
+
+## 6. icon\_vac\_bypass.ico 设计(AI自动化图标生成描述)
+
+**prompt:**
+
+```
+A 128x128 Windows .ico file with large bold letters "VAC" in white or pale blue, on a dark or black background. Below the letters, a thick, clear, horizontal arrow (→ or --__>) passes underneath, visually suggesting "bypass" or "tunneling". The style should match classic tray icons—minimal, high-contrast, not cartoonish. Keep the icon readable at 16x16.
+```
+
+---
+
+## 7. 其它说明
+
+* 所有自动化脚本与补丁操作**必须**严格遵循此 agents.md。
+* 具体代码注释需要使用英语
diff --git a/Build SnapKey/CMAKE-Build/CMake-Build.bat b/Build SnapKey/CMAKE-Build/CMake-Build.bat
index def6cc2..4b3ca31 100644
--- a/Build SnapKey/CMAKE-Build/CMake-Build.bat
+++ b/Build SnapKey/CMAKE-Build/CMake-Build.bat
@@ -1,14 +1,28 @@
@echo off
+setlocal
+
+rem ========== · ==========
+set THISDIR=%~dp0
+set CMAKE=%THISDIR%cmake-4.1.0-rc2-windows-x86_64\bin\cmake.exe
+set MINGW=%THISDIR%mingw64
+set PATH=%MINGW%\bin;%PATH%
+
+rem ========== ==========
+echo [+] Configuring CMake...
+"%CMAKE%" -S "%THISDIR%..\.." -B "%THISDIR%build" -G "MinGW Makefiles"
+
+if %errorlevel% neq 0 (
+ echo [!] CMake configure failed.
+ pause
+ exit /b 1
+)
+
+echo [+] Building with MinGW...
+"%CMAKE%" --build "%THISDIR%build"
+
+if exist "%THISDIR%build\SnapKey.exe" (
+ copy /Y "%THISDIR%build\SnapKey.exe" "%THISDIR%" >nul
+)
-mkdir build > nul
-cd build > nul
-echo [+] Preparing files...
-cmake .. > nul
-echo [+] Compiling...
-cmake --build . > nul
-cd .. > nul
-move "build\Debug\SnapKey.exe" "." > nul
echo [+] Done!
-rmdir /s /q build > nul
-echo [+] Press a key to exit...
-pause > nul
\ No newline at end of file
+pause
diff --git a/Build SnapKey/CMAKE-Build/CMakeLists.txt b/Build SnapKey/CMAKE-Build/CMakeLists.txt
index 4efd636..346adae 100644
--- a/Build SnapKey/CMAKE-Build/CMakeLists.txt
+++ b/Build SnapKey/CMAKE-Build/CMakeLists.txt
@@ -9,7 +9,7 @@ set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} /MT")
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /MTd")
set(BUILD_SHARED_LIBS OFF)
-add_executable(SnapKey SnapKey.cpp resources.rc)
+add_executable(SnapKey WIN32 SnapKey.cpp resources.rc)
if (WIN32)
set_target_properties(SnapKey PROPERTIES
diff --git a/README.md b/README.md
index c9591f1..21e99f2 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,4 @@
-[](https://github.com/cafali/SnapKey/releases)
+
**About SnapKey**
--------------------------------------------------------------------------------------------------
@@ -10,7 +10,28 @@ SnapKey is a lightweight, open-source tool that operates from the system tray an
[](https://github.com/cafali/SnapKey/wiki/Compatibility-List)
+### **New in v1.2.9 – Experimental VAC/CS2 Bypass Modes 🚫🎮**
+---
+
+SnapKey v1.2.9 introduces two **experimental bypass modes** aimed at improving compatibility with games that impose stricter input policies, such as **Counter-Strike 2 (CS2)**. These modes can be toggled independently in the configuration file and allow SnapKey to remain active while circumventing CS2’s built-in restrictions on background input automation.
+
+> ⚙️ **VAC Bypass A** — Simulates real-time user input using a lower-level system call chain.
+> ⚙️ **VAC Bypass B** — Uses synthetic input injection with randomized timings to mimic human behavior more accurately.
+
+Both modes are entirely optional and **disabled by default**. When enabled, SnapKey will change its tray icon to indicate **VAC bypass mode** is active:
+
+* ✅ A curved arrow wrapping around the "VAC" label appears.
+* ⛔ This visually reminds users that advanced compatibility workarounds are enabled.
+
+
+> \[!WARNING]
+> These features are **experimental** and **not officially endorsed by Valve or any game publisher**. While SnapKey does not directly modify any game files or memory, **use of automation tools may still violate Terms of Service** for certain games.
+> **Use at your own risk.**
+
+For details on how these bypass modes work and how to enable them, refer to the [**Bypass Modes Wiki Page**](https://github.com/cafali/SnapKey/wiki/VAC-Bypass-Modes).
+
+---
Download
--------------------------------------------------------------------------------------------------
@@ -120,12 +141,13 @@ Looking for More Information? Got Questions or Need Help?
@cafali
- @minteeaa
+ @minteeaa
+ @felix3322
@Yaw-Dev
-
-
+
+
-
+
\ No newline at end of file
diff --git a/SnapKey.cpp b/SnapKey.cpp
index 96a047c..bb8fcba 100644
--- a/SnapKey.cpp
+++ b/SnapKey.cpp
@@ -1,4 +1,4 @@
-// SnapKey 1.2.8
+// SnapKey 1.2.9
// github.com/cafali/SnapKey
#include
@@ -8,6 +8,9 @@
#include
#include
#include
+#include
+#include
+#include
using namespace std;
@@ -17,8 +20,10 @@ using namespace std;
#define ID_TRAY_REBIND_KEYS 3002
#define ID_TRAY_LOCK_FUNCTION 3003
#define ID_TRAY_RESTART_SNAPKEY 3004
-#define ID_TRAY_HELP 3005 // v1.2.8
-#define ID_TRAY_CHECKUPDATE 3006 // v1.2.8
+#define ID_TRAY_HELP 3005 // v1.2.9
+#define ID_TRAY_CHECKUPDATE 3006 // v1.2.9
+#define ID_TRAY_VAC_BYPASS_A 3007
+#define ID_TRAY_VAC_BYPASS_B 3008
#define WM_TRAYICON (WM_USER + 1)
struct KeyState
@@ -42,6 +47,15 @@ HHOOK hHook = NULL;
HANDLE hMutex = NULL;
NOTIFYICONDATA nid;
bool isLocked = false; // Variable to track the lock state
+bool vacBypassAEnabled = false; // VAC bypass A toggle
+bool vacBypassBEnabled = false; // VAC bypass B toggle
+int vacCounter = 0; // counter for imperfect snaptap
+int vacAMinDelay = 15; // A mode minimum overlap delay
+int vacAMaxDelay = 35; // A mode maximum overlap delay
+int vacBMinDelay = 5; // B mode minimum release-press interval
+int vacBMaxDelay = 15; // B mode maximum release-press interval
+
+static std::mt19937 rng(std::random_device{}());
// Function declarations
LRESULT CALLBACK KeyboardProc(int nCode, WPARAM wParam, LPARAM lParam);
@@ -49,9 +63,11 @@ LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
void InitNotifyIconData(HWND hwnd);
bool LoadConfig(const std::string& filename);
void CreateDefaultConfig(const std::string& filename);
-void RestoreConfigFromBackup(const std::string& backupFilename, const std::string& destinationFilename);
-std::string GetVersionInfo();
+void RestoreConfigFromBackup(const std::string& backupFilename, const std::string& destinationFilename);
+std::string GetVersionInfo();
void SendKey(int target, bool keyDown);
+void UpdateTrayIcon();
+void WriteConfigValue(const std::string& filename, const std::string& key, int value);
int main()
{
@@ -100,6 +116,7 @@ int main()
// Initialize and add the system tray icon
InitNotifyIconData(hwnd);
+ UpdateTrayIcon();
// Set the hook
hHook = SetWindowsHookEx(WH_KEYBOARD_LL, KeyboardProc, NULL, 0);
@@ -139,9 +156,9 @@ void handleKeyDown(int keyCode)
if (!currentKeyInfo.keyDown)
{
currentKeyInfo.keyDown = true;
- SendKey(keyCode, true);
if (currentGroupInfo.activeKey == 0 || currentGroupInfo.activeKey == keyCode)
{
+ SendKey(keyCode, true);
currentGroupInfo.activeKey = keyCode;
}
else
@@ -149,7 +166,31 @@ void handleKeyDown(int keyCode)
currentGroupInfo.previousKey = currentGroupInfo.activeKey;
currentGroupInfo.activeKey = keyCode;
- SendKey(currentGroupInfo.previousKey, false);
+ if (vacBypassBEnabled && std::uniform_int_distribution(0,1)(rng) == 0)
+ {
+ SendKey(currentGroupInfo.previousKey, false);
+ std::this_thread::sleep_for(std::chrono::milliseconds(
+ std::uniform_int_distribution(vacBMinDelay, vacBMaxDelay)(rng)));
+ SendKey(keyCode, true);
+ }
+ else
+ {
+ SendKey(keyCode, true);
+ if (vacBypassAEnabled)
+ {
+ if (vacCounter >= 17)
+ {
+ std::this_thread::sleep_for(std::chrono::milliseconds(
+ std::uniform_int_distribution(vacAMinDelay, vacAMaxDelay)(rng)));
+ vacCounter = 0;
+ }
+ else
+ {
+ vacCounter++;
+ }
+ }
+ SendKey(currentGroupInfo.previousKey, false);
+ }
}
}
}
@@ -243,6 +284,32 @@ void InitNotifyIconData(HWND hwnd)
Shell_NotifyIcon(NIM_ADD, &nid);
}
+void UpdateTrayIcon()
+{
+ const TCHAR* iconFile = TEXT("icon.ico");
+ if (isLocked)
+ {
+ iconFile = TEXT("icon_off.ico");
+ }
+ else if (vacBypassAEnabled || vacBypassBEnabled)
+ {
+ iconFile = TEXT("icon_vac_bypass.ico");
+ }
+
+ HICON hIcon = (HICON)LoadImage(NULL, iconFile, IMAGE_ICON, 0, 0, LR_LOADFROMFILE);
+ if (!hIcon)
+ {
+ hIcon = (HICON)LoadImage(NULL, TEXT("icon.ico"), IMAGE_ICON, 0, 0, LR_LOADFROMFILE);
+ }
+
+ if (hIcon)
+ {
+ nid.hIcon = hIcon;
+ Shell_NotifyIcon(NIM_MODIFY, &nid);
+ DestroyIcon(hIcon);
+ }
+}
+
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
@@ -260,11 +327,13 @@ LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
AppendMenu(hMenu, MF_STRING, ID_TRAY_REBIND_KEYS, TEXT("Rebind Keys"));
AppendMenu(hMenu, MF_STRING, ID_TRAY_RESTART_SNAPKEY, TEXT("Restart SnapKey"));
AppendMenu(hMenu, MF_STRING, ID_TRAY_LOCK_FUNCTION, isLocked ? TEXT("Enable SnapKey") : TEXT("Disable SnapKey")); // dynamicly switch between state
+ AppendMenu(hMenu, MF_STRING | (vacBypassAEnabled ? MF_CHECKED : 0), ID_TRAY_VAC_BYPASS_A, TEXT("VAC bypass A"));
+ AppendMenu(hMenu, MF_STRING | (vacBypassBEnabled ? MF_CHECKED : 0), ID_TRAY_VAC_BYPASS_B, TEXT("VAC bypass B"));
// support & info
AppendMenu(hMenu, MF_SEPARATOR, 0, NULL);
AppendMenu(hMenu, MF_STRING, ID_TRAY_HELP, TEXT("Get Help"));
AppendMenu(hMenu, MF_STRING, ID_TRAY_CHECKUPDATE, TEXT("Check Updates"));
- AppendMenu(hMenu, MF_STRING, ID_TRAY_VERSION_INFO, TEXT("Version Info (1.2.8)"));
+ AppendMenu(hMenu, MF_STRING, ID_TRAY_VERSION_INFO, TEXT("Version Info (1.2.9)"));
AppendMenu(hMenu, MF_SEPARATOR, 0, NULL);
// exit
AppendMenu(hMenu, MF_STRING, ID_TRAY_EXIT_CONTEXT_MENU_ITEM, TEXT("Exit SnapKey"));
@@ -279,28 +348,7 @@ LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
isLocked = !isLocked;
// Update the tray icon
- if (isLocked)
- {
- // Load icon_off.ico (OFF)
- HICON hIconOff = (HICON)LoadImage(NULL, TEXT("icon_off.ico"), IMAGE_ICON, 0, 0, LR_LOADFROMFILE);
- if (hIconOff)
- {
- nid.hIcon = hIconOff;
- Shell_NotifyIcon(NIM_MODIFY, &nid);
- DestroyIcon(hIconOff);
- }
- }
- else
- {
- // Load icon.ico (ON)
- HICON hIconOn = (HICON)LoadImage(NULL, TEXT("icon.ico"), IMAGE_ICON, 0, 0, LR_LOADFROMFILE);
- if (hIconOn)
- {
- nid.hIcon = hIconOn;
- Shell_NotifyIcon(NIM_MODIFY, &nid);
- DestroyIcon(hIconOn);
- }
- }
+ UpdateTrayIcon();
}
break;
@@ -353,15 +401,21 @@ LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
case ID_TRAY_LOCK_FUNCTION: // lock sticky keys
{
isLocked = !isLocked;
- HICON hIcon = isLocked
- ? (HICON)LoadImage(NULL, TEXT("icon_off.ico"), IMAGE_ICON, 0, 0, LR_LOADFROMFILE)
- : (HICON)LoadImage(NULL, TEXT("icon.ico"), IMAGE_ICON, 0, 0, LR_LOADFROMFILE);
- if (hIcon)
- {
- nid.hIcon = hIcon;
- Shell_NotifyIcon(NIM_MODIFY, &nid);
- DestroyIcon(hIcon);
- }
+ UpdateTrayIcon();
+ }
+ break;
+ case ID_TRAY_VAC_BYPASS_A: // toggle VAC bypass A
+ {
+ vacBypassAEnabled = !vacBypassAEnabled;
+ WriteConfigValue("config.cfg", "vac_bypass_a", vacBypassAEnabled ? 1 : 0);
+ UpdateTrayIcon();
+ }
+ break;
+ case ID_TRAY_VAC_BYPASS_B: // toggle VAC bypass B
+ {
+ vacBypassBEnabled = !vacBypassBEnabled;
+ WriteConfigValue("config.cfg", "vac_bypass_b", vacBypassBEnabled ? 1 : 0);
+ UpdateTrayIcon();
}
break;
}
@@ -379,7 +433,7 @@ LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
// version information window
std::string GetVersionInfo() {
- return "SnapKey v1.2.8 (R17)\n"
+ return "SnapKey v1.2.9 (R17)\n"
"Version Date: June 19, 2025\n"
"Repository: github.com/cafali/SnapKey\n"
"License: MIT License\n";
@@ -396,7 +450,6 @@ void RestoreConfigFromBackup(const std::string& backupFilename, const std::strin
MessageBox(NULL, TEXT("Default config restored from backup successfully."), TEXT("SnapKey"), MB_ICONINFORMATION | MB_OK);
} else {
// backup.snapkey copy failed
- DWORD error = GetLastError();
std::string errorMsg = "Failed to restore config from backup.";
MessageBox(NULL, errorMsg.c_str(), TEXT("SnapKey Error"), MB_ICONERROR | MB_OK);
}
@@ -409,6 +462,35 @@ void CreateDefaultConfig(const std::string& filename)
RestoreConfigFromBackup(backupFilename, filename);
}
+void WriteConfigValue(const std::string& filename, const std::string& key, int value)
+{
+ std::ifstream inFile(filename);
+ std::vector lines;
+ bool found = false;
+ if (inFile.is_open()) {
+ std::string line;
+ std::regex pat("^\\s*" + key + "\\s*=");
+ while (getline(inFile, line)) {
+ if (std::regex_search(line, pat)) {
+ lines.push_back(key + " = " + std::to_string(value));
+ found = true;
+ } else {
+ lines.push_back(line);
+ }
+ }
+ inFile.close();
+ }
+
+ if (!found) {
+ lines.push_back(key + " = " + std::to_string(value));
+ }
+
+ std::ofstream outFile(filename, std::ios::trunc);
+ for (const auto& l : lines) {
+ outFile << l << "\n";
+ }
+}
+
// Check for config.cfg
bool LoadConfig(const std::string& filename)
{
@@ -420,6 +502,10 @@ bool LoadConfig(const std::string& filename)
string line; // Check for duplicated keys in the config file
int id = 0;
+ bool foundA = false, foundB = false;
+ bool foundAMin = false, foundAMax = false;
+ bool foundBMin = false, foundBMax = false;
+
while (getline(configFile, line)) {
istringstream iss(line);
string key;
@@ -431,6 +517,7 @@ bool LoadConfig(const std::string& filename)
}
else if (getline(iss, key, '=') && (iss >> value))
{
+ key = regex_replace(key, regex("^\\s+|\\s+$"), "");
if (key.find("key") != string::npos)
{
if (!KeyInfo[value].registered)
@@ -445,7 +532,43 @@ bool LoadConfig(const std::string& filename)
return false;
}
}
+ else if (key == "vac_bypass_a") {
+ vacBypassAEnabled = (value != 0); foundA = true;
+ }
+ else if (key == "vac_bypass_b") {
+ vacBypassBEnabled = (value != 0); foundB = true;
+ }
+ else if (key == "vac_a_min_delay") {
+ vacAMinDelay = value; foundAMin = true;
+ }
+ else if (key == "vac_a_max_delay") {
+ vacAMaxDelay = value; foundAMax = true;
+ }
+ else if (key == "vac_b_min_delay") {
+ vacBMinDelay = value; foundBMin = true;
+ }
+ else if (key == "vac_b_max_delay") {
+ vacBMaxDelay = value; foundBMax = true;
+ }
}
}
+ configFile.close();
+
+ if (vacAMinDelay < 0 || vacAMaxDelay < 0 || vacAMaxDelay < vacAMinDelay) {
+ vacAMinDelay = 15;
+ vacAMaxDelay = 35;
+ }
+ if (vacBMinDelay < 0 || vacBMaxDelay < 0 || vacBMaxDelay < vacBMinDelay) {
+ vacBMinDelay = 5;
+ vacBMaxDelay = 15;
+ }
+
+ if (!foundA) WriteConfigValue(filename, "vac_bypass_a", vacBypassAEnabled ? 1 : 0);
+ if (!foundB) WriteConfigValue(filename, "vac_bypass_b", vacBypassBEnabled ? 1 : 0);
+ if (!foundAMin) WriteConfigValue(filename, "vac_a_min_delay", vacAMinDelay);
+ if (!foundAMax) WriteConfigValue(filename, "vac_a_max_delay", vacAMaxDelay);
+ if (!foundBMin) WriteConfigValue(filename, "vac_b_min_delay", vacBMinDelay);
+ if (!foundBMax) WriteConfigValue(filename, "vac_b_max_delay", vacBMaxDelay);
+
return true;
-}
\ No newline at end of file
+}
diff --git a/config.cfg b/config.cfg
index 367cb70..2728971 100644
--- a/config.cfg
+++ b/config.cfg
@@ -82,5 +82,16 @@ key4=87
# NUM5 - 101
# NUM6 - 102
# NUM7 - 103
-# NUM8 - 104
-# NUM9 - 105
+# NUM8 - 104
+# NUM9 - 105
+
+# VAC Bypass config
+vac_bypass_a = 1 # 1=enable 0=disable
+vac_bypass_b = 0 # 1=enable 0=disable
+
+# VAC Bypass delay settings (ms)
+vac_a_min_delay = 15 # A mode minimum overlap delay
+vac_a_max_delay = 35 # A mode maximum overlap delay
+
+vac_b_min_delay = 5 # B mode minimum release-press interval
+vac_b_max_delay = 15 # B mode maximum release-press interval
diff --git a/icon_vac_bypass.ico b/icon_vac_bypass.ico
new file mode 100644
index 0000000..9e5b77e
Binary files /dev/null and b/icon_vac_bypass.ico differ
diff --git a/meta/backup.snapkey b/meta/backup.snapkey
index 367cb70..2728971 100644
--- a/meta/backup.snapkey
+++ b/meta/backup.snapkey
@@ -82,5 +82,16 @@ key4=87
# NUM5 - 101
# NUM6 - 102
# NUM7 - 103
-# NUM8 - 104
-# NUM9 - 105
+# NUM8 - 104
+# NUM9 - 105
+
+# VAC Bypass config
+vac_bypass_a = 1 # 1=enable 0=disable
+vac_bypass_b = 0 # 1=enable 0=disable
+
+# VAC Bypass delay settings (ms)
+vac_a_min_delay = 15 # A mode minimum overlap delay
+vac_a_max_delay = 35 # A mode maximum overlap delay
+
+vac_b_min_delay = 5 # B mode minimum release-press interval
+vac_b_max_delay = 15 # B mode maximum release-press interval
diff --git a/resources.rc b/resources.rc
index dd025d0..89f1106 100644
--- a/resources.rc
+++ b/resources.rc
@@ -5,8 +5,8 @@ IDI_ICON1 ICON "snapkey.ico"
// Version information
1 VERSIONINFO
-FILEVERSION 1,2,8,0
-PRODUCTVERSION 1,2,8,0
+FILEVERSION 1,2,9,0
+PRODUCTVERSION 1,2,9,0
FILEOS 0x40004
FILETYPE 0x1
{
@@ -20,8 +20,8 @@ FILETYPE 0x1
VALUE "CompanyName", "cafali"
VALUE "LegalCopyright", "Copyright \xA9 2025 cafali - MIT License (github.com/cafali/SnapKey)"
VALUE "ProductName", "SnapKey"
- VALUE "FileVersion", "1.2.8.0"
- VALUE "ProductVersion", "1.2.8.0"
+ VALUE "FileVersion", "1.2.9.0"
+ VALUE "ProductVersion", "1.2.9.0"
}
}