AtariHackerMCP

Herramientas que uno podría necesitar para hackear código Atari de 8 bits (archivos .atr), incluyendo volcado hexadecimal, desensamblador, tablas de símbolos, etc.

Documentación

AtariHackerMCP

Un servidor MCP local para ingeniería inversa de binarios Atari de 8 bits e imágenes de disco ATR. Admite análisis de desensamblado de múltiples pasadas, separación de código/datos, salida consciente de segmentos, inyección de archivos ATR, scripting por lotes y una tabla de símbolos completa del hardware Atari.

Requisitos

  • .NET SDK 10.0+
  • Linux, macOS o Windows

Compilación

Restaurar paquetes y compilar:

dotnet build

Publicar una compilación de lanzamiento si es necesario:

dotnet publish -c Release -o publish

Ejecución

Este servidor utiliza el transporte stdio de MCP, por lo que normalmente lo lanza un cliente MCP en lugar de ejecutarse de forma interactiva.

Para pruebas locales:

dotnet run --no-build

O ejecutar el ejecutable publicado:

./publish/AtariHackerMCP

Configuración del Cliente MCP

Ejemplo de entrada de servidor stdio:

{
  "mcpServers": {
    "atari-hacker": {
      "command": "dotnet",
      "args": [
        "run",
        "--project",
        "/absolute/path/to/AtariHackerMCP/AtariHackerMCP.csproj",
        "--no-build"
      ]
    }
  }
}

Si prefieres usar una compilación publicada:

{
  "mcpServers": {
    "atari-hacker": {
      "command": "/absolute/path/to/AtariHackerMCP/publish/AtariHackerMCP",
      "args": []
    }
  }
}

Herramientas Disponibles

Herramientas de archivos y discos

  • load_rom — Cargar un binario ROM/XEX en la sesión actual
  • rom_info — Mostrar información estructural sobre el binario cargado
  • atr_info — Mostrar información estructural sobre una imagen de disco ATR
  • atr_header — Mostrar los campos de cabecera ATR de una imagen de disco
  • load_atr_file — Extraer un archivo de un ATR y cargarlo en la sesión
  • load_atr_boot — Extraer sectores de arranque de un ATR y cargarlos en $0700
  • list_atr_directory — Listar el directorio DOS de una imagen de disco ATR
  • analyze_boot_sector — Decodificar la cabecera del sector de arranque de un ATR
  • sector_dump — Volcado hexadecimal de sectores de un ATR por número de sector lógico
  • search_boot_sector — Escanear sectores de arranque en múltiples ATR para patrones/diferencias
  • extract_atr_file — Extraer un archivo de un ATR y guardarlo en disco
  • inject_atr_file — Inyectar un archivo en un ATR (copiar al escribir)
  • create_atr — Crear una nueva imagen de disco ATR desde cero
  • write_atr_sector — Escribir datos sin procesar en un sector específico de un ATR
  • write_atr_file — Escribir un archivo en un ATR con creación de entrada de directorio
  • define_filesystem — Definir un diseño de sistema de archivos personalizado para ATR que no sean DOS

Inspección y desensamblado

  • hex_dump — Producir un volcado hexadecimal con desplazamientos de archivo, direcciones de memoria y ASCII
  • disassemble — Desensamblar código 6502 con análisis opcional de múltiples pasadas (analyze=true)
    • Admite formatos: listing, ca65, atasm, mac65
    • Cuando analyze=true: genera etiquetas significativas (sub_XXXX, data_XXXX, jmp_XXXX), separación de código/datos, salida .segment/.proc/.endproc consciente de segmentos, formato de cadenas ATASCII, comentarios de cabecera de procedimiento
  • analyze_disassembly — Análisis de múltiples pasadas que construye un grafo de referencias e identifica regiones de código/datos
    • Formatos: summary, graph, labels, full
  • define_segment — Definir un segmento de memoria por tipo (código, datos, gráficos, texto, zero_page)
  • remove_segment — Eliminar un segmento definido por nombre
  • list_segments — Listar todos los segmentos de memoria definidos (muestra huecos)
  • clear_segments — Borrar todos los segmentos definidos
  • generate_linker_config — Generar una configuración de enlazador cc65 a partir de los segmentos actuales

Herramientas de análisis

  • x_ref — Encontrar referencias cruzadas a una dirección en la ROM
  • find_pattern — Buscar un patrón de bytes con comodines
  • find_strings — Buscar secuencias de caracteres ASCII o ATASCII imprimibles
  • trace_control_flow — Trazar estáticamente la ejecución desde una dirección inicial
  • probe_data — Analizar un rango de memoria para identificar el tipo de datos (texto, gráficos, tabla, charset, lista de visualización, datos de sprite, datos de mapa) con puntuación de confianza
  • generate_callgraph — Generar un grafo de llamadas que muestre las relaciones entre subrutinas (formato Mermaid o texto)
  • analyze_coverage — Analizar la cobertura de código: qué bytes se ejecutan frente a datos
  • diff_roms — Comparar dos archivos ROM o ATR (formato resumen, detallado o diff hexadecimal)

Herramientas de símbolos y página cero

  • define_symbol — Añadir o actualizar una etiqueta con nombre para una dirección de memoria
  • remove_symbol — Eliminar un símbolo definido por el usuario
  • lookup_symbol — Buscar la entrada de símbolo para una dirección
  • list_symbols — Listar símbolos en la tabla de símbolos
  • set_symbols — Habilitar/deshabilitar grupos de símbolos (hardware, variables del SO, ROM del SO, etiquetas de usuario) para controlar qué nombres aparecen en el desensamblado
  • load_labels — Cargar etiquetas y segmentos desde un archivo sidecar
  • save_labels — Guardar etiquetas y segmentos actuales en un archivo sidecar
  • annotate_zero_page — Añadir o actualizar una anotación de página cero
  • show_zero_page_map — Mostrar anotaciones actuales de página cero

Herramientas de scripting

  • run_script — Ejecutar una secuencia de comandos desde un archivo de script (admite 33 comandos)

Herramientas de utilidad

  • calculate — Evaluar expresiones matemáticas con literales hexadecimales (prefijo $)
  • hex_to_decimal — Convertir hexadecimal a decimal
  • decimal_to_hex — Convertir decimal a hexadecimal

Desensamblado de Múltiples Pasadas

Cuando se pasa analyze=true a disassemble, el motor realiza tres pasadas:

  1. Pasada 1 — Recopilación de Referencias: Escanea todos los límites de instrucciones en la ROM, registrando destinos JSR, destinos JMP, destinos de ramas, destinos de saltos indirectos y referencias de datos absolutas/indirectas en un ReferenceGraph.
  2. Pasada 2 — Trazado de Regiones de Código: Desde cada punto de entrada de código, traza el flujo de ejecución (siguiendo JSR, JMP, ramas, deteniéndose en RTS/RTI/BRK) para marcar bytes como código o datos.
  3. Pasada 3 — Generación de Etiquetas: Produce etiquetas significativas (sub_XXXX, jmp_XXXX, data_XXXX, L_XXXX) con un orden de prioridad adecuado (usuario > subrutina > datos > hardware > SO > rama).

Ejemplo

; --------------------------------------------------
; Generated by Atari Hacker MCP v4
; --------------------------------------------------

.segment "MAIN_CODE"
.org $0C00

; --------------------------------------------------
; Subroutine: game_init
; Calls:     load_ag_obj, load_ag_dat, main_loop
; --------------------------------------------------
.proc game_init
    LDA #$00
    STA $D400          ; DMACTL
    ...
.endproc

; String table at $1712
credits_text:
    .byte "Scholastic", $9B    ; $9B = ATASCII EOL
    .byte "Wizware", $9B
    .byte $00

Tabla de Símbolos del Hardware Atari

La tabla de símbolos integrada cubre más de 200 entradas en todos los componentes principales de Atari:

GrupoRangoEntradas
GTIA$D000–$D01F22 registros (gráficos de jugador/proyectil, color, control)
POKEY$D200–$D21F32 registros (sonido, E/S, reservados, alias de lectura/escritura)
PIA$D300–$D3034 registros (E/S paralela)
ANTIC$D400–$D41F20 registros (DMA, lista de visualización, NMI, reservados)
OS ROM$C000–$FFFF13 puntos de entrada (SIO, CIO, vectores)
Página cero del SO$00–$FF~220 variables (temporizadores, control de E/S, punto flotante, pantalla, paddles, joysticks)

Los grupos de símbolos se pueden alternar con set_symbols para evitar conflictos cuando el código de usuario se superpone con los rangos de direcciones del SO.

Operaciones de Escritura ATR

El subsistema de escritura ATR proporciona modificación de imágenes de disco con copia al escribir:

OperaciónDescripción
extract_atr_fileExtraer un archivo DOS de un ATR al sistema de archivos del host
inject_atr_fileReemplazar los datos de una entrada de archivo en un ATR (crea una copia .modified)
create_atrCrear un ATR en blanco con un número de sectores y densidad especificados
write_atr_sectorEscribir datos binarios sin procesar en un sector específico
write_atr_fileCrear una nueva entrada de archivo DOS con asignación de sectores
define_filesystemDescribir un diseño de sistema de archivos no DOS para discos de formato personalizado

Scripting por Lotes

La herramienta run_script ejecuta secuencias de comandos desde archivos de texto:

# disassemble_all.txt
load_rom filePath=game.xex
define_symbol address=$1540 label=game_init
define_segment name=boot_loader start=$0700 end=$087F type=code
define_segment name=main_code start=$0C00 end=$1CFF type=code
disassemble offset=$0700 numBytes=384 format=ca65 analyze=true
generate_linker_config output=game.cfg
save_labels filePath=game.annotations.json

Sondeo de Datos

probe_data utiliza 7 heurísticas para identificar tipos de datos en rangos de memoria:

  • Detección de cadenas — Secuencias imprimibles ATASCII/ASCII, terminadas en $9B, terminadas en nulo
  • Detección de relleno — Secuencias de $00, $FF, $1A (EOL ATASCII)
  • Detección de conjuntos de caracteres — Bloques de 1024 bytes (128×8) y 512 bytes (64×8)
  • Detección de tablas — Tablas de direcciones de 2 bytes, tablas de búsqueda de 1 byte
  • Detección de listas de visualización — Opcodes de lista de visualización ANTIC con extracción LMS
  • Detección de datos de sprite — Bloques alineados de 8/16/32 bytes con análisis de variedad de bytes
  • Detección de datos de mapa — Patrones de cuadrícula 2D con longitudes de fila consistentes

Cada resultado incluye un nivel de confianza (Alto/Medio/Bajo) y detalles de respaldo.

Flujo de Trabajo Típico

Exploración básica

  1. Cargar un archivo con load_rom, load_atr_file o load_atr_boot.
  2. Inspeccionar la estructura con rom_info o atr_info.
  3. Usar hex_dump para examinar bytes sin procesar, find_strings para localizar texto.
  4. Desensamblar con disassemble (modo básico).

Desensamblado guiado por análisis

  1. load_rom → Cargar el binario.
  2. analyze_disassembly format=summary → Obtener una visión general de código/datos.
  3. analyze_disassembly format=labels → Ver todas las etiquetas generadas automáticamente.
  4. probe_data start=$1712 end=$1AD4 → Identificar regiones de datos.
  5. define_segment name=main_code start=$0C00 end=$1CFF type=code
  6. define_segment name=game_data start=$1D00 end=$BBA4 type=data
  7. disassemble offset=$0C00 numBytes=5376 format=ca65 analyze=true → Salida consciente de segmentos.
  8. generate_callgraph start=$1540 depth=5 format=mermaid → Visualizar la estructura.
  9. Iterar: define_symbol → disassemble analyze=true → revisar.

Flujo de trabajo de refinamiento iterativo

  1. load_rom → desensamblado inicial con etiquetas automáticas.
  2. analyze_disassembly → identificar regiones de código/datos.
  3. define_symbol → anotar direcciones clave.
  4. define_segment → marcar regiones de código/datos.
  5. save_labels → persistir anotaciones.
  6. disassemble analyze=true → volver a desensamblar con anotaciones.
  7. Revisar, repetir los pasos 3-6 según sea necesario.

Flujo de trabajo de modificación ATR

  1. create_atr output=build/disk.atr sectors=720 density=sd → disco en blanco.
  2. write_atr_sector filePath=build/disk.atr sector=1 input=boot.bin → escribir sector de arranque.
  3. write_atr_file filePath=build/disk.atr name=AGENT.OBJ input=build/AGENT.OBJ → añadir archivo.
  4. extract_atr_file filePath=game.atr name=AGENT.OBJ output=extracted/AGENT.OBJ → extraer archivo.
  5. inject_atr_file filePath=game.atr name=AGENT.OBJ input=build/AGENT.OBJ → reemplazar archivo.

Persistencia

Los símbolos definidos por el usuario, las anotaciones de página cero y las definiciones de segmentos se guardan automáticamente en un archivo JSON sidecar junto al objetivo cargado:

<rom-or-synthetic-path>.atarihacker.json

El formato sidecar v4 incluye:

  • Campo de versión para compatibilidad futura
  • Hash SHA-256 de la ROM para verificación de integridad
  • Segmentos (nombre, tipo, inicio, fin, comentario)
  • Definiciones de sistema de archivos personalizadas

Los archivos sidecar v3 (sin campo de versión) se leen de forma transparente y se actualizan al guardar.

Ejemplo de Prueba de Humo MCP

Esto envía initialize y tools/list directamente a través de stdio:

(
  printf '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-03-26","capabilities":{},"clientInfo":{"name":"test-client","version":"1.0"}}}\n'
  sleep 0.2
  printf '{"jsonrpc":"2.0","id":2,"method":"tools/list","params":{}}\n'
  sleep 1
) | dotnet run --no-build

Notas

  • Los registros se escriben en stderr para que stdout permanezca limpio para el tráfico JSON-RPC de MCP.
  • La herramienta disassemble con analyze=false (predeterminado) se comporta exactamente como en v3: compatibilidad total hacia atrás.
  • El código automodificable y el despacho por tabla de saltos (JMP (table,X)) no se pueden resolver estáticamente; usa define_segment para marcar esas regiones manualmente.
  • Para detalles completos del diseño, consulta docs/version4-design.md y la especificación v4.

Licencia

Este proyecto está licenciado bajo la Licencia MIT. Consulta el archivo LICENSE para más detalles.