Autonomous troubleshooting workflow for Amiberry bugs. Use this when investigating, reproducing, or fixing bugs in Amiberry. Provides a complete edit-build-run-test-fix cycle using the Amiberry MCP server tools for process management, IPC control, screenshot analysis, log monitoring, and crash detection.
Install
npx skillscat add blitterstudio/amiberry/troubleshoot-amiberry Install via the SkillsCat registry.
Amiberry Autonomous Troubleshooting
Debug and fix Amiberry bugs through iterative edit-build-run-test-fix cycles with minimal user interaction.
Bug to investigate
$ARGUMENTS
Environment
Amiberry source is at the current working directory (or a nearby amiberry/ directory).
The MCP server (amiberry-mcp-server) provides tools for runtime control.
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 MinGW-w64/GCC 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 -j$(nproc)Windows host targeting WSL2
wsl -e bash -c "cd ~/amiberry && cmake --build build -j$(nproc)"Windows (native MinGW-w64)
# Use the helper script (sets PATH for CLion's cmake/ninja/mingw, VCPKG_ROOT)
powershell -ExecutionPolicy Bypass -File "build_and_run.ps1"
# Or manually:
$env:VCPKG_ROOT = "D:\Github\vcpkg"
cmake --preset windows-debug
cd out/build/windows-debug
ninja -j12
# Run with logging enabled
.\amiberry.exe --logWindows build notes:
- Build dir:
out/build/windows-debug(orwindows-release) - Kill stale
amiberry.exebefore rebuild if "permission denied" write_log()is silent unless--logflag orwrite_logfileconfig is set- JIT is non-functional on 64-bit Windows (interpreter mode works fine)
- 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
Grepto find related functions, variables, error messages - Use
Globto 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 3: Fix
- Make code changes using Edit tool on 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 -j$(nproc) - 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 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
Available MCP Tools Reference
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 HOME directory is
~/Library/Application Support/Amiberry(contains a space). - 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 - 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 toggles (current)
AMIBERRY_ARM64_GUARD_VERBOSE=1: enables detailed dynamic guard learning logs (per key/window). Keep this off for normal runs.- Optional ARM64 hotspot guard is OFF by default for performance.
AMIBERRY_ARM64_ENABLE_HOTSPOT_GUARD=1: re-enables optional hotspot logic for A/B diagnostics.AMIBERRY_ARM64_DISABLE_HOTSPOT_GUARD=1: forces optional hotspot logic off; fixed ARM64 safety fallback for the known Lightwave startup hotspot remains active.- 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: SDL2 synthesizes
SDL_MOUSEBUTTONDOWN/SDL_MOUSEMOTIONfrom touch events by default. Fix: filterevent.button.which == SDL_TOUCH_MOUSEID/event.motion.which == SDL_TOUCH_MOUSEIDin mouse event handlers when on-screen joystick is active (done inamiberry.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: SDL2 synthesizes
On-screen joystick not appearing in Input dropdown: The virtual device must be registered in
init_joystick()(amiberry_input.cpp). Check thatnum_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: MinGW links
msvcrt.dllwhich doesn't support"ccs=UTF-8"fopen mode (errno=22). Fixed with plain"w"/"rt"/"wt"modes under#ifdef AMIBERRYincfgfile.cppandini.cpp. - 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.