Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 12 additions & 3 deletions .github/workflows/ahk-lint-format-compile.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,11 @@ jobs:
- uses: actions/checkout@v6

- name: Install AutoHotkey v1.1 (Portable)
run: choco install autohotkey.portable --version=1.1.37.02 -y
run: choco install autohotkey.portable -y
shell: pwsh

- name: Install AutoHotkey v2
run: choco install autohotkey --version=2.0.19 -y
run: choco install autohotkey -y
shell: pwsh

- name: Verify Installations
Expand All @@ -40,8 +40,17 @@ jobs:

- name: Syntax Check & Format Validation
run: |
$compilerV1 = "C:\ProgramData\chocolatey\lib\autohotkey.portable\tools\Compiler\Ahk2Exe.exe"
# Dynamically find Ahk2Exe in the portable package
$compilerV1Obj = Get-ChildItem -Path "C:\ProgramData\chocolatey\lib\autohotkey.portable" -Filter "Ahk2Exe.exe" -Recurse -ErrorAction SilentlyContinue | Select-Object -First 1
if ($compilerV1Obj) {
$compilerV1 = $compilerV1Obj.FullName
Write-Host "Found v1 compiler: $compilerV1"
} else {
$compilerV1 = "C:\ProgramData\chocolatey\lib\autohotkey.portable\tools\Compiler\Ahk2Exe.exe"
Write-Host "Warning: Could not find Ahk2Exe via search, using default" -ForegroundColor Yellow
}
$compilerV2 = "$env:ProgramFiles\AutoHotkey\Compiler\Ahk2Exe.exe"
if (!(Test-Path $compilerV2)) { $compilerV2 = $compilerV1; Write-Host "Using v1 compiler for v2 fallback" }
$tempDir = New-Item -Type Directory -Force "$env:TEMP\ahk-$(Get-Random)"
$syntaxErrors = @()
$formatIssues = @()
Expand Down
134 changes: 74 additions & 60 deletions Other/Citra_mods/Citra_3DS_Manager.ahk
Original file line number Diff line number Diff line change
Expand Up @@ -53,20 +53,30 @@ ScanMods(){
}

;----------------- Config Helpers -----------------
RegExEscape(str){
static specials := "()[]{}?*+|^$.\"
out := ""
Loop, Parse, str
out .= InStr(specials, A_LoopField) ? "\" A_LoopField : A_LoopField
return out
}
UpdateConfig(content, updates){
newContent := ""
remaining := updates.Clone()

Loop, Parse, content, `n, `r
{
line := A_LoopField
pos := InStr(line, "=")
if (pos > 1){
keyCandidate := RTrim(SubStr(line, 1, pos-1))

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Using RTrim here only removes whitespace from the right side of the key. If a key in the configuration file has leading whitespace (e.g., key = value), it will be parsed incorrectly as " key", and the update for "key" will be missed. Using Trim instead will handle both leading and trailing whitespace, making the parsing more robust to formatting variations in the config file.

       keyCandidate := Trim(SubStr(line, 1, pos-1))

if (remaining.HasKey(keyCandidate)){
val := remaining[keyCandidate]
line := keyCandidate "=" val
Comment on lines +67 to +68
Copy link

Copilot AI Feb 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The value retrieved from the updates map is not trimmed before being written to the config line. While the key is trimmed using RTrim on line 65, the value could potentially have leading or trailing whitespace that should be handled consistently. Consider whether values should also be trimmed, or if this is intentional to preserve exact values from the updates map.

Copilot uses AI. Check for mistakes.
remaining.Delete(keyCandidate)
}
Comment on lines +65 to +70
Copy link

Copilot AI Feb 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indentation is inconsistent in this block. Lines 65, 67, 68, and 69 use extra spaces instead of the standard 2-space indentation pattern used throughout the file. This should be corrected to match the surrounding code's indentation style.

Suggested change
keyCandidate := RTrim(SubStr(line, 1, pos-1))
if (remaining.HasKey(keyCandidate)){
val := remaining[keyCandidate]
line := keyCandidate "=" val
remaining.Delete(keyCandidate)
}
keyCandidate := RTrim(SubStr(line, 1, pos-1))
if (remaining.HasKey(keyCandidate)){
val := remaining[keyCandidate]
line := keyCandidate "=" val
remaining.Delete(keyCandidate)
}

Copilot uses AI. Check for mistakes.
}
newContent .= line "`n"
Comment on lines +60 to +72
Copy link

Copilot AI Feb 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Loop Parse delimiter n with r stripped will normalize line endings to LF only (Unix-style), but the function then appends "n" (LF) to each line. This means the output will have LF line endings regardless of what the input file had. If the original qt-config.ini uses CRLF line endings (Windows standard), this changes the file format. Consider preserving the original line ending style or explicitly using CRLF ("r`n") for Windows compatibility, as specified in the repository's coding guidelines.

Copilot uses AI. Check for mistakes.
}

SetKey(content, key, value){
pat := "m)^(" . RegExEscape(key) . ")\s*=.*$"
if (RegExMatch(content, pat))
return RegExReplace(content, pat, "$1=" value, , 1)
else
return content "`n" key "=" value
for k, v in remaining {
newContent .= k "=" v "`n"
}

return SubStr(newContent, 1, -1)
}

LoadConfig(){
Expand Down Expand Up @@ -95,65 +105,69 @@ ApplyPreset(game){
return "Config missing"

norm := NormKey(game)
updates := {}

; defaults
cfg := SetKey(cfg, "resolution_factor", "10")
cfg := SetKey(cfg, "texture_filter_name", "xBRZ freescale")
cfg := SetKey(cfg, "texture_filter_name\\default", "false")
cfg := SetKey(cfg, "pp_shader_name", "Bump_Mapping_AA_optimize")
cfg := SetKey(cfg, "pp_shader_name\\default", "false")
cfg := SetKey(cfg, "preload_textures\\default", "false")
cfg := SetKey(cfg, "preload_textures", "true")
cfg := SetKey(cfg, "cpu_clock_percentage", "125")
cfg := SetKey(cfg, "layout_option", "2")
updates["resolution_factor"] := "10"
updates["texture_filter_name"] := "xBRZ freescale"
updates["texture_filter_name\\default"] := "false"
updates["pp_shader_name"] := "Bump_Mapping_AA_optimize"
updates["pp_shader_name\\default"] := "false"
updates["preload_textures\\default"] := "false"
updates["preload_textures"] := "true"
updates["cpu_clock_percentage"] := "125"
updates["layout_option"] := "2"

if (norm = "3d_land"){
cfg := SetKey(cfg, "resolution_factor", "8")
cfg := SetKey(cfg, "texture_filter_name", "none")
cfg := SetKey(cfg, "texture_filter_name\\default", "true")
cfg := SetKey(cfg, "pp_shader_name", "none (builtin)")
cfg := SetKey(cfg, "pp_shader_name\\default", "false")
cfg := SetKey(cfg, "preload_textures", "false")
cfg := SetKey(cfg, "preload_textures\\default", "true")
updates["resolution_factor"] := "8"
updates["texture_filter_name"] := "none"
updates["texture_filter_name\\default"] := "true"
updates["pp_shader_name"] := "none (builtin)"
updates["pp_shader_name\\default"] := "false"
updates["preload_textures"] := "false"
updates["preload_textures\\default"] := "true"
} else if (norm = "hd_texture_pack"){
cfg := SetKey(cfg, "resolution_factor", "4")
cfg := SetKey(cfg, "texture_filter_name", "none")
cfg := SetKey(cfg, "texture_filter_name\\default", "true")
cfg := SetKey(cfg, "pp_shader_name", "none (builtin)")
cfg := SetKey(cfg, "pp_shader_name\\default", "false")
cfg := SetKey(cfg, "preload_textures", "false")
cfg := SetKey(cfg, "preload_textures\\default", "true")
updates["resolution_factor"] := "4"
updates["texture_filter_name"] := "none"
updates["texture_filter_name\\default"] := "true"
updates["pp_shader_name"] := "none (builtin)"
updates["pp_shader_name\\default"] := "false"
updates["preload_textures"] := "false"
updates["preload_textures\\default"] := "true"
} else if (norm = "luigi_s_mansion_2"){
cfg := SetKey(cfg, "resolution_factor", "6")
cfg := SetKey(cfg, "cpu_clock_percentage", "25")
updates["resolution_factor"] := "6"
updates["cpu_clock_percentage"] := "25"
} else if (norm = "mario_kart_7"){
cfg := SetKey(cfg, "resolution_factor", "5")
cfg := SetKey(cfg, "texture_filter_name", "none")
cfg := SetKey(cfg, "texture_filter_name\\default", "true")
cfg := SetKey(cfg, "preload_textures", "false")
cfg := SetKey(cfg, "preload_textures\\default", "true")
updates["resolution_factor"] := "5"
updates["texture_filter_name"] := "none"
updates["texture_filter_name\\default"] := "true"
updates["preload_textures"] := "false"
updates["preload_textures\\default"] := "true"
} else if (norm = "mario_luigi_bowser_s_inside_story"){
cfg := SetKey(cfg, "layout_option", "0")
cfg := SetKey(cfg, "texture_filter_name", "none")
cfg := SetKey(cfg, "texture_filter_name\\default", "true")
cfg := SetKey(cfg, "pp_shader_name", "none (builtin)")
cfg := SetKey(cfg, "pp_shader_name\\default", "false")
cfg := SetKey(cfg, "preload_textures", "false")
cfg := SetKey(cfg, "preload_textures\\default", "true")
updates["layout_option"] := "0"
updates["texture_filter_name"] := "none"
updates["texture_filter_name\\default"] := "true"
updates["pp_shader_name"] := "none (builtin)"
updates["pp_shader_name\\default"] := "false"
updates["preload_textures"] := "false"
updates["preload_textures\\default"] := "true"
} else if (norm = "mario_luigi"){
cfg := SetKey(cfg, "layout_option", "0")
updates["layout_option"] := "0"
} else if (norm = "no_preloading"){
cfg := SetKey(cfg, "preload_textures", "false")
cfg := SetKey(cfg, "preload_textures\\default", "true")
updates["preload_textures"] := "false"
updates["preload_textures\\default"] := "true"
} else if (norm = "nsmb2"){
cfg := SetKey(cfg, "resolution_factor", "10")
cfg := SetKey(cfg, "texture_filter_name", "none")
cfg := SetKey(cfg, "texture_filter_name\\default", "true")
cfg := SetKey(cfg, "pp_shader_name", "none (builtin)")
cfg := SetKey(cfg, "pp_shader_name\\default", "false")
cfg := SetKey(cfg, "preload_textures", "false")
cfg := SetKey(cfg, "preload_textures\\default", "true")
updates["resolution_factor"] := "10"
updates["texture_filter_name"] := "none"
updates["texture_filter_name\\default"] := "true"
updates["pp_shader_name"] := "none (builtin)"
updates["pp_shader_name\\default"] := "false"
updates["preload_textures"] := "false"
updates["preload_textures\\default"] := "true"
}

cfg := UpdateConfig(cfg, updates)

if (!SaveConfig(cfg))
return "Failed to write config"
return ""
Expand Down
Loading