⚠️ Clean-Room / Educativo

Este proyecto es educativo y Open Source. No se copia código de otros emuladores. Implementación basada únicamente en documentación técnica y tests permitidas.

Debug: Extensión Final del Trazado de CPU a 2000 Instrucciones

Fecha: 2025-12-20 Step ID: 0156 Estado: 🔍 DRAFT

Resumen

El análisis de la traza de 500 instrucciones (Step 0155) confirmó que los bucles de limpieza de memoria de la ROM de Tetris son extremadamente largos y consumen toda la ventana de depuración actual. Se aumentó el límite de traza de la CPU de 500 a 2000 instrucciones para garantizar la captura de la secuencia de código que se ejecuta después de que todos los bucles de inicialización hayan finalizado. Sin embargo, el análisis de la nueva traza reveló que incluso con 2000 instrucciones, todavía estamos dentro de los bucles de inicialización, lo que indica que estos bucles son aún más extensos de lo esperado.

Concepto de Hardware

Las rutinas de inicialización de las ROMs de Game Boy pueden ser extremadamente complejas y extensas. Los bucles de limpieza de memoria no solo limpian una única región, sino que pueden limpiar múltiples regiones de memoria en secuencia:

  • WRAM (0xC000-0xDFFF): Memoria de trabajo de 8 KB que debe ser inicializada a cero.
  • HRAM (0xFF80-0xFFFE): Memoria de alta velocidad de 127 bytes.
  • OAM (0xFE00-0xFE9F): Memoria de atributos de objetos (sprites).
  • Otras regiones: Dependiendo del juego, pueden limpiarse otras áreas de memoria.

Cada región puede requerir cientos o miles de iteraciones de un bucle, y estos bucles pueden estar anidados (un bucle externo que controla múltiples bucles internos). Esto explica por qué incluso 2000 instrucciones pueden no ser suficientes para observar el final completo de la inicialización.

Fuente: Pan Docs - Memory Map, Boot ROM, Initialization Routines

Implementación

Se modificó la constante DEBUG_INSTRUCTION_LIMIT en el archivo src/core/cpp/CPU.cpp para aumentar el límite de instrucciones trazadas de 500 a 2000.

Componentes modificados

  • CPU.cpp: Aumento de DEBUG_INSTRUCTION_LIMIT de 500 a 2000.

Cambio realizado

// Variables estáticas para logging de diagnóstico
static int debug_instruction_counter = 0;
// Aumentamos el límite drásticamente a 2000 para superar todos los bucles de inicialización.
static const int DEBUG_INSTRUCTION_LIMIT = 2000;

Archivos Afectados

  • src/core/cpp/CPU.cpp - Aumento de DEBUG_INSTRUCTION_LIMIT de 500 a 2000.

Tests y Verificación

Este cambio no requiere tests unitarios específicos, ya que solo modifica el límite de logging de diagnóstico. La validación se realizó mediante:

  • Recompilación del módulo C++: Ejecutado .\rebuild_cpp.ps1 exitosamente.
  • Ejecución del emulador: Ejecutado python main.py roms/tetris.gb para generar la nueva traza extendida.
  • Análisis de la traza: Se capturaron exactamente 2000 instrucciones.

Resultados del Análisis

Estadísticas de la traza:

  • Total de instrucciones capturadas: 2000
  • Bucle principal (0x0293-0x0295): Cada dirección se ejecuta 663 veces
  • Instrucciones fuera del bucle principal: Solo 2 apariciones de 0x0297 y 0x0298
  • Últimas 20 instrucciones: Todas están dentro del bucle (0x0293-0x0295)

Hallazgos Clave

El análisis reveló que incluso con 2000 instrucciones, todavía estamos dentro de los bucles de inicialización:

  • El bucle principal (0x0293-0x0295) se ejecuta más de 660 veces, consumiendo aproximadamente 1989 instrucciones de las 2000 disponibles.
  • Hay evidencia de bucles anidados: se observan instrucciones en 0x0297 (DEC C) y 0x0298 (JR NZ), sugiriendo que hay un bucle externo que controla el bucle interno.
  • No se observaron opcodes de configuración de hardware (0xE0, 0xEA, 0xCD) en la traza, lo que indica que todavía no hemos llegado a la fase de configuración de la PPU.

Fragmento de la Traza Final

[CPU TRACE 1995] PC: 0x0294 | Opcode: 0x05
[CPU TRACE 1996] PC: 0x0295 | Opcode: 0x20
[CPU TRACE 1997] PC: 0x0293 | Opcode: 0x32
[CPU TRACE 1998] PC: 0x0294 | Opcode: 0x05
[CPU TRACE 1999] PC: 0x0295 | Opcode: 0x20

Fuentes Consultadas

  • Análisis del Step 0155: Confirmación de que 500 instrucciones son insuficientes.
  • Pan Docs - Memory Map: Descripción de las regiones de memoria que deben limpiarse durante la inicialización.
  • Comportamiento observado en trazas de CPU: Los bucles de inicialización pueden ser extremadamente largos.

Integridad Educativa

Lo que Entiendo Ahora

  • Bucles de inicialización extensos: Los bucles de limpieza de memoria pueden ejecutarse cientos o miles de veces, consumiendo miles de instrucciones.
  • Bucles anidados: Puede haber múltiples niveles de bucles anidados, donde un bucle externo controla varios bucles internos.
  • Límites de traza: Incluso límites aparentemente grandes (2000 instrucciones) pueden ser insuficientes para capturar rutinas de inicialización completas.

Lo que Falta Confirmar

  • Punto de salida completo: Necesitamos identificar cuántas iteraciones más se requieren para salir completamente de todos los bucles de inicialización.
  • Estrategia alternativa: Podríamos necesitar implementar un mecanismo de traza condicional que se active solo después de ciertos puntos de interés, en lugar de trazar todas las instrucciones desde el inicio.
  • Configuración de hardware: Una vez que salgamos de los bucles, necesitamos identificar qué opcodes se usan para configurar la PPU y otros componentes de hardware.

Hipótesis y Suposiciones

Hipótesis principal: Los bucles de inicialización de Tetris son extremadamente largos, posiblemente limpiando múltiples regiones de memoria de 8 KB cada una. Es posible que necesitemos aumentar el límite aún más (a 5000 o 10000) o implementar una estrategia de traza condicional para poder observar qué ocurre después de la inicialización.

Próximos Pasos

  • [ ] Evaluar si es necesario aumentar el límite aún más (a 5000 o 10000 instrucciones).
  • [ ] Considerar implementar un mecanismo de traza condicional que se active solo después de ciertos puntos de interés.
  • [ ] Analizar la ROM directamente para identificar qué opcodes están en las direcciones después de los bucles de inicialización.
  • [ ] Verificar si hay más bucles de limpieza después de 0x0298 o si comienza la configuración de hardware.
  • [ ] Una vez que identifiquemos el final de los bucles, implementar los opcodes faltantes para que el juego pueda continuar su ejecución.