name: troubleshoot-amiberry description: Use when investigating, reproducing, or fixing Amiberry bugs, especially renderer or input regressions, HiDPI or SDL3 logical-presentation bugs, Vulkan capability or swapchain failures, crash regressions, or behavior regressions. Follow an edit-build-run-test-fix cycle, using Amiberry MCP runtime-control tools when they are configured and falling back to normal process, log, screenshot, and debugger tools otherwise.
Amiberry Autonomous Troubleshooting
Debug and fix Amiberry bugs through iterative edit-build-run-test-fix cycles with minimal user interaction.
Environment
Amiberry source is at the current working directory (or a nearby amiberry/ directory).
If the Amiberry MCP server (amiberry-mcp-server) is configured, use it for runtime control and observation. If it is not available, fall back to normal process launch, logs, screenshots, and debugger tools.
Determine the platform before building:
- macOS: Build natively with
cmake - Linux / WSL2: Build with
cmake(usewsl -eprefix if on Windows host) - Windows (native): Build with llvm-mingw (clang + lld) via CMake presets and Ninja
Build Commands
Linux / macOS
# Configure (first time or after CMake changes)
cmake -B build -DCMAKE_BUILD_TYPE=Debug -DUSE_IPC_SOCKET=ON
# Build (subsequent changes)
cmake --build build --parallel
Windows host targeting WSL2
wsl -e bash -c "cd ~/amiberry && cmake --build build --parallel"
Windows (native llvm-mingw)
# Use the helper script if present (sets PATH for cmake/ninja/llvm-mingw, VCPKG_ROOT, LLVM_MINGW_ROOT)
powershell -ExecutionPolicy Bypass -File "build_and_run.ps1"
# Or manually:
$env:LLVM_MINGW_ROOT = "C:\llvm-mingw"
$env:VCPKG_ROOT = "D:\Github\vcpkg"
cmake --preset windows-debug
cd out/build/windows-debug
ninja -j12
# Run with logging enabled
.\amiberry.exe --log
Windows build notes:
- Build dir:
out/build/windows-debug(orwindows-release) - Toolchain: llvm-mingw (clang + lld + libc++) via
cmake/Toolchain-x86_64-w64-mingw32.cmake. The MinGW-w64 / GCC build was retired; do not try to mix GCC and clang outputs. LLVM_MINGW_ROOTmust point at an extracted llvm-mingw release (orC:\llvm-mingw\binmust be on PATH)- Kill stale
amiberry.exebefore rebuild if "permission denied" write_log()is silent unless--logflag orwrite_logfileconfig is set- x86-64 JIT is supported on Windows; for high-natmem, pointer-width, or performance regressions use the
amiberry-x86-jitskill - PowerShell
$env:variables get stripped in bash inline commands; use.ps1files with-File
Troubleshooting Workflow
Phase 1: Understand the Bug
- Read the bug description / issue carefully
- Identify which subsystem is likely involved (graphics, input, audio, CPU emulation, chipset, config, GUI, etc.)
- Search the codebase for relevant code:
- Use
rgto find related functions, variables, error messages - Use
rg --filesto find relevant source files - Read the code to understand the current behavior
- Use
- Form a hypothesis about the root cause
Phase 2: Reproduce
Launch Amiberry with appropriate config:
- Use
launch_and_wait_for_ipcto start Amiberry and wait for IPC readiness - Specify a model (
A500,A1200, etc.) or config file as needed - This automatically enables logging
- Use
Verify it's running:
- Use
health_checkto confirm process + IPC + emulation status
- Use
Set up the reproduction scenario:
- Use
runtime_load_configto load specific configurations - Use
runtime_insert_floppyto insert disk images - Use
send_keyto navigate menus or trigger actions - Use
runtime_set_configto change specific options
- Use
Observe the behavior:
- Use
runtime_screenshot_viewto see what's on screen - Use
tail_logto monitor log output - Use
runtime_get_fpsto check performance - Use
runtime_get_cpu_regs/runtime_get_custom_regsfor hardware state
- Use
If it crashes:
- Use
get_crash_infoto detect the crash and analyze signals + log patterns - Use
get_process_infofor exit code and signal details
- Use
Phase 2a: Split Shared Bugs Into Concrete Paths
Before editing, decide whether the bug is in a shared subsystem or only one renderer/input path.
- Treat these coordinate spaces as distinct:
- Window coordinates: raw SDL event coordinates
- Drawable pixel coordinates: OpenGL/Vulkan backbuffer size
- Render/logical coordinates: SDL renderer logical presentation space
- For SDL renderer logical-presentation bugs, pass raw window coordinates to SDL conversion helpers such as
SDL_RenderCoordinatesFromWindow()orSDL_ConvertEventToRenderCoordinates(). Do not pre-scale and then ask SDL to scale again. - Check mouse, pen, and tablet paths together. If only
SDL_EVENT_MOUSE_MOTIONis fixed, stylus/tablet input often remains offset. - Separate renderer-specific behavior before changing code:
- SDL renderer path:
SDL_Renderer, logical presentation, viewport, pen/mouse conversion - OpenGL path: drawable size, external shaders, texture filtering, OSD path
- Vulkan path: instance/device/swapchain capability probing, no SDL renderer fallback assumptions
- SDL renderer path:
- When debugging visual regressions, verify the exact path that owns the blur or scaling issue. OSD textures, main frame textures, and external shader input textures are different paths and should not be "fixed" together by assumption.
Phase 3: Fix
- Make code changes using
apply_patchon the Amiberry source files - Keep changes minimal - fix only what's broken, don't refactor surrounding code
- Kill the running instance: Use
kill_amiberry - Rebuild:
cmake --build build --parallel - Check build output for errors. If build fails, fix and retry.
Phase 4: Verify
Restart with same config: Use
restart_amiberryorlaunch_and_wait_for_ipcRun the same reproduction steps from Phase 2
Check results:
runtime_screenshot_view- does the screen look correct?tail_log- are there still errors/warnings?get_crash_info- did it crash again?health_check- is everything still running?
If NOT fixed: Go back to Phase 3 with new hypothesis
If fixed: Clean up and report findings
Phase 4a: Renderer And Capability Verification
- For HiDPI issues, test both SDL renderer and OpenGL/Vulkan paths when relevant. A fix in one path does not prove the others are correct.
- For Vulkan startup failures, gate everything against reported capabilities:
- composite alpha from
supportedCompositeAlpha - image usage bits such as
TRANSFER_DST_BIT - present modes and surface formats
- composite alpha from
- Prefer "probe, then enable" over hardcoding spec-preferred flags.
- If the bug involves presentation or scaling, verify both startup and post-resize behavior.
Phase 5: Report
Summarize:
- What the bug was (root cause)
- What was changed (files and line numbers)
- How to verify the fix
- Any side effects or concerns
Amiberry MCP Tools Reference
Use these tools when the Amiberry MCP server is available in the current session.
Process Lifecycle
| Tool | Purpose |
|---|---|
check_process_alive |
Is Amiberry running? Returns PID + exit code |
get_process_info |
Detailed info: PID, status, signal, crash detection |
kill_amiberry |
Force kill (SIGTERM then SIGKILL) |
wait_for_exit |
Block until process exits (with timeout) |
restart_amiberry |
Kill + relaunch with same command |
Workflow
| Tool | Purpose |
|---|---|
launch_and_wait_for_ipc |
Launch with logging, wait for IPC ready |
health_check |
Combined: process + IPC ping + status + FPS |
Observation
| Tool | Purpose |
|---|---|
runtime_screenshot_view |
Screenshot returned as image data |
tail_log |
New log lines since last read |
wait_for_log_pattern |
Wait for regex in log (with timeout) |
get_crash_info |
Process signals + log crash pattern scanning |
Emulation Control
| Tool | Purpose |
|---|---|
pause_emulation / resume_emulation |
Pause/resume |
reset_emulation |
Soft or hard reset |
frame_advance |
Step N frames when paused |
runtime_set_config / runtime_get_config |
Change/query config at runtime |
runtime_load_config |
Load a .uae config file |
Debugging
| Tool | Purpose |
|---|---|
runtime_get_cpu_regs |
All CPU registers (D0-D7, A0-A7, PC, SR) |
runtime_get_custom_regs |
Custom chip registers (DMACON, INTENA, etc.) |
runtime_read_memory |
Read Amiga memory (1/2/4 bytes) |
runtime_write_memory |
Write Amiga memory |
runtime_disassemble |
Disassemble at address |
runtime_set_breakpoint / runtime_clear_breakpoint |
Breakpoints |
runtime_debug_activate / runtime_debug_step |
Debugger control |
runtime_debug_step_over |
Step over JSR/BSR |
runtime_get_copper_state / runtime_get_blitter_state |
Hardware state |
Media & Display
| Tool | Purpose |
|---|---|
runtime_insert_floppy / runtime_eject_floppy |
Floppy management |
runtime_insert_cd / runtime_eject_cd |
CD management |
send_key |
Send keyboard input (Amiga keycodes) |
runtime_set_display_mode |
Window/fullscreen/fullwindow |
runtime_set_ntsc |
PAL/NTSC switching |
Amiga Keycodes (common)
| Key | Code | Key | Code |
|---|---|---|---|
| Return | 0x44 | Space | 0x40 |
| Escape | 0x45 | Backspace | 0x41 |
| Up | 0x4C | Down | 0x4D |
| Left | 0x4F | Right | 0x4E |
| F1-F10 | 0x50-0x59 | Help | 0x5F |
| Left Amiga | 0x66 | Right Amiga | 0x67 |
| A-Z | 0x20,0x35,0x33,0x22,0x12,0x23,0x24,0x25,0x17,0x26,0x27,0x28,0x37,0x36,0x18,0x19,0x10,0x13,0x21,0x14,0x16,0x34,0x11,0x32,0x15,0x31 |
To send a keypress, call send_key twice: once with state=1 (press), then state=0 (release).
Key Source Directories
| Directory | Contents |
|---|---|
src/ |
Core emulation (UAE-derived) |
src/osdep/ |
Platform abstraction (Linux/macOS/Android/Windows) |
src/osdep/imgui/ |
GUI panels (Dear ImGui) |
src/include/ |
Headers and interfaces |
src/osdep/amiberry_ipc_socket.cpp |
IPC socket implementation |
src/osdep/amiberry_gfx.cpp |
Graphics/display |
src/osdep/amiberry_input.cpp |
Input handling |
src/osdep/amiberry.cpp |
Core platform layer |
src/osdep/macos_bookmarks.h/.mm |
macOS security-scoped bookmarks (App Store) |
macOS Path Notes
- macOS user data now defaults to
~/Documents/Amiberry; startup migration handles legacy~/Library/Application Support/Amiberry. - When constructing shell commands with paths, always quote arguments.
download_file()properly quotes paths in curl/wget commands viapopen().create_missing_amiberry_folders()usesstd::filesystem::copy()instead ofsystem("cp -R ...").- The app bundle at
build/Amiberry.appstores resources (controllers, data, roms, whdboot) underResources/.
Tips
- Always use
--log(handled automatically bylaunch_and_wait_for_ipc) for log output - Use
tail_logfrequently to catch errors early - If the screen looks wrong,
pause_emulation+runtime_screenshot_viewgives a stable frame - If a fix touches input coordinates, explicitly note which coordinate space each variable is in
- If a fix touches rendering quality, verify OSD, main frame, and external shader paths independently
- For timing-sensitive bugs, use
runtime_set_configto change CPU speed or floppy speed - For crashes, the signal name in
get_crash_infotells you a lot: SIGSEGV = null pointer/bad memory, SIGABRT = assertion/abort, SIGBUS = alignment - Build with Debug type (
-DCMAKE_BUILD_TYPE=Debug) for better crash info - If you need to test multiple configs, use
kill_amiberry+launch_and_wait_for_ipcbetween each
ARM64 JIT testing
- ARM64 JIT stability checks should be validated with at least 3 configs: SysInfo, A4000, and Lightwave.
Input & On-Screen Joystick Troubleshooting
On-screen D-pad acts like a mouse instead of joystick: Two possible causes:
- SDL touch-to-mouse synthesis: SDL3 can synthesize
SDL_EVENT_MOUSE_BUTTON_*/SDL_EVENT_MOUSE_MOTIONfrom touch events. Fix: filterevent.button.which == SDL_TOUCH_MOUSEID/event.motion.which == SDL_TOUCH_MOUSEIDin mouse event handlers when on-screen joystick or the on-screen keyboard is active. Pen/stylus paths also useSDL_PEN_MOUSEIDfiltering inamiberry_input.cpp. - Wrong port assignment: Another device (e.g., Android accelerometer) may be assigned to Port 1, overriding the on-screen joystick. The on-screen joystick auto-assigns to Port 1 via
on_screen_joystick_set_enabled(true), but checkchanged_prefs.jports[1].idto verify.
- SDL touch-to-mouse synthesis: SDL3 can synthesize
On-screen joystick not appearing in Input dropdown: The virtual device is only registered when
currprefs.onscreen_joystickis enabled. Check this preference first. Then verify registration ininit_joystick()(input_platform_internal_host.h):num_joystick < MAX_INPUT_DEVICESandosj_device_indexis set. The device appears as "On-Screen Joystick" in the joystick device list.Input injection debugging: Use
--logflag. The on-screen joystick logs"On-Screen Joystick registered as JOY%d"at startup. Usesetjoystickstate()/setjoybuttonstate()(proper device API); avoidsend_input_event()which bypasses port mode configuration.Port mode mismatch: If port 1 mode is not
JSEM_MODE_JOYSTICK, D-pad input may behave as mouse. The auto-assignment setschanged_prefs.jports[1].mode = JSEM_MODE_JOYSTICKand callsinputdevice_config_change().
Windows-Specific Troubleshooting
- Black screen with USE_OPENGL: Usually caused by JIT
jit_abort()→uae_reset()permanently settingquit_program, which blocks pixel drawing inwaitqueue(). Fixed insrc/jit/x86/compemu_x86.h. - GUI crash only with debugger: Debug builds (
-DDEBUG) enableassert()in tinyxml2. This can cause crashes with debugger attached but not in normal execution. Not a real bug. - Symlink failures in WHDBooter: Windows requires admin or Developer Mode for symlinks. Directory symlinks use
std::filesystem::copy()directly. File symlinks have try-catch fallback. - Winsock differences:
close()→closesocket(),ioctl()→ioctlsocket(),errno→WSAGetLastError(). Checksrc/slirp/for patterns. - No log output:
write_log()returns early if neither--lognorwrite_logfileis enabled. Always pass--logwhen debugging. - GUI crash on startup (missing data dir): If the
data/directory (fonts, icons) is missing from the runtime working directory, ImGui'sAddFontFromFileTTFasserts and crashes in debug builds (exit code 3). Fix:main_window.cppchecksstd::filesystem::exists(font_path)before loading. Deployment fix: copydata/from source tree to working directory. - Config save does nothing: WinUAE-style
"ccs=UTF-8"modes and POSIX'e'close-on-exec modes are not portable across Amiberry's Windows path. Use plain"w"/"rt"/"wt"modes under#ifdef AMIBERRYincfgfile.cpp/ini.cpp, and useuae_fopen()for paths that need'e'stripped on Windows. - Hardfile RDB not detected in GUI: ImGui
hd.cppwas missinghardfile_testrdb()call after HDF file selection, causing geometry to stay at 32,1,2 instead of auto-detecting RDB (0,0,0). Fixed in commitc2b5c053.