Buscar/Crea un emulador que reproduzca el bus y la temporización del hardware real

Crea un emulador que reproduzca el bus y la temporización del hardware real

Úsalo al crear o corregir un emulador. Divide el código por piezas del hardware, copia el bus, la temporización y el DMA del hardware real, prueba con programas que pasan en el equipo real y mantiene estables los estados guardados y la API pública.

Para usar estas reglas de IA
## Explica el código inusual y ejecuta las comprobaciones de tipos y los tests Escriba el código del emulador para ingenieros que quizá no conozcan el hardware original. Explique por qué existe una regla de temporización, un efecto secundario o una solución alternativa, en vez de suponer que una implementación inusual se explica por sí sola. Enlace referencias autorizadas sobre el hardware cuando ayuden a aclarar el comportamiento. Localice y utilice los comandos documentados del repositorio para formato, linting, comprobación de tipos, pruebas, compilaciones, modo de vigilancia y pruebas de rendimiento. Trate las comprobaciones obligatorias como parte del cambio: - Ejecute el formato y las pruebas específicas durante las iteraciones. - Ejecute la comprobación de tipos cuando cambien declaraciones públicas o límites tipados. - Ejecute la suite completa y autorizada antes de confirmar cambios o realizar la entrega. - Ejecute la prueba de rendimiento ante cambios importantes o posibles regresiones de rendimiento. - Mantenga la refactorización no relacionada separada de una corrección específica. Actualice los ejemplos públicos y las referencias de la API cuando cambien métodos, opciones, callbacks, exportaciones o formatos de entrada admitidos. Coloque los detalles locales de implementación en comentarios cercanos; reserve la guía del proyecto para la arquitectura y las reglas aplicables a varios componentes. ## Divide el emulador en componentes que sigan las piezas del hardware Organice el emulador en torno a los subsistemas de hardware que modela. Utilice un orquestador pequeño para coordinar los componentes y exponer callbacks de renderizado, audio, estado y actualizaciones de memoria persistente. Separe las responsabilidades de procesadores, vídeo, audio, mapeo de cartuchos o memoria, carga de programas, auxiliares de renderizado, controladores y serialización. Proporcione una interfaz clara a cada componente y permita que gestione su propio estado interno. Utilice herencia únicamente cuando las variantes de hardware compartan un verdadero comportamiento base y sobrescriban reglas concretas de mapeo o conmutación de bancos. Prefiera la composición para subsistemas independientes y evite el acceso oculto a través de los límites de los componentes. Defina una base de tiempo común. La ejecución por fotogramas sigue requiriendo un recuento preciso de ciclos dentro de cada fotograma, mientras que las aplicaciones anfitrionas siguen siendo responsables de la temporización de presentación y de la planificación. Centralice la conversión de estados guardados mediante contratos simétricos de serialización y restauración utilizados por todos los componentes con estado. ## Reproduce cada lectura y escritura del bus, incluidos los accesos ficticios Modele el bus como un comportamiento con estado, no como una simple consulta de dirección a valor. El hardware real puede conservar el valor más reciente, devolver datos retenidos desde direcciones no mapeadas o de solo escritura, o controlar únicamente determinados bits. Mantenga registros de retención separados cuando distintos buses de hardware conserven estados independientes. Actualice el registro correspondiente en cada carga, escritura, operación de pila, lectura de código de operación y lectura de vector de interrupción que sea observable. Cuando un dispositivo controle solo una parte de un valor, combine esos bits con el estado retenido del bus exactamente como lo hace el hardware. Implemente las lecturas y escrituras ficticias como operaciones reales del bus. Pueden actualizar valores retenidos y activar efectos secundarios de E/S incluso cuando el programa nunca utilice el valor devuelto. Codifique explícitamente la secuencia del bus para cada modo de direccionamiento: - El direccionamiento indexado puede leer una dirección intermedia antes de corregir la página. - El indexado de página cero puede leer la dirección sin indexar antes de aplicar el índice. - El indexado indirecto puede leer un puntero o una dirección intermedia antes de llegar a la dirección efectiva. - Las instrucciones de almacenamiento y de lectura-modificación-escritura pueden realizar accesos ficticios obligatorios incluso sin cruzar una página. - Una instrucción de lectura-modificación-escritura puede escribir el valor original antes de escribir el valor modificado. Conserve el orden específico de cada instrucción cuando una lectura ocurra antes o después de una operación de pila. Reordenar operaciones que producen los mismos valores finales en los registros puede seguir siendo incorrecto de forma observable en el bus. ## Sincroniza los dispositivos a mitad de instrucción y trata el DMA como ciclos reales del bus Cuando el emulador ejecuta un componente de forma atómica, pero el hardware real hace avanzar los componentes al unísono, pueden aparecer estados obsoletos al acceder a registros durante una instrucción. Corrija esta situación en el límite donde el acceso se vuelve observable. Registre cuántas operaciones de bus ha completado la instrucción actual. Antes de leer o escribir un registro de un dispositivo sincronizado, haga avanzar ese dispositivo según la proporción exacta de ciclos de reloj correspondiente a las operaciones transcurridas. Reste el trabajo ya aplicado del avance posterior a nivel de fotograma para que el tiempo nunca se cuente dos veces. Modele la creación de la bandera de interrupción por separado de la entrega de la interrupción. Un control de inhibición puede impedir que se cree una bandera de estado, en lugar de limitarse a suprimir la señal de interrupción externa. Las pruebas deben distinguir estos comportamientos. Represente DMA como la toma de control de ciclos reales del bus. Una transferencia puede alterar el valor actual del bus, retrasar el avance del procesador o cambiar el resultado de instrucciones cuya salida depende del estado del bus. Conserve el orden entre DMA, los accesos de las instrucciones y los efectos secundarios de los dispositivos. Implemente las instrucciones no oficiales o de casos límite documentadas únicamente a partir de referencias y pruebas fiables. No simplifique su comportamiento por ciclos solo porque el software habitual no las utilice. ## Prueba con programas que se sabe que pasan en el hardware real Utilice varias capas de pruebas, cada una con un propósito distinto: - Las pruebas unitarias verifican la inicialización, la semántica de las instrucciones, las reglas de mapeo, el reflejo de memoria, las transiciones de estado y la gestión de errores. - Las pruebas de regresión específicas fijan búferes de fotogramas, muestras de audio, trazas del bus u otras salidas deterministas. - Los arneses de integración ejecutan programas de diagnóstico fiables y comparan estados detallados de la máquina o códigos de error. - Las suites de precisión del hardware cubren interacciones que las pruebas aisladas de instrucciones no pueden revelar. Considere correctos los programas de referencia consolidados cuando se sepa que funcionan en hardware real. Investigue el emulador, el arnés, el fixture y el entorno antes de culpar al programa de referencia. Registre explícitamente los fallos aceptados con un motivo concreto y limitado. Una lista de fallos conocidos no autoriza a ocultar regresiones nuevas ni a ampliar una excepción existente. Compruebe tanto los valores finales como el orden de las operaciones cuando el hardware pueda observar accesos intermedios. Añada un caso de regresión siempre que una corrección de la especificación o un comportamiento anteriormente mal clasificado cambie la implementación. ## Haz que los estados guardados se restauren por completo y detén la ejecución tras un fallo Los estados guardados deben incluir todos los componentes que afecten a la ejecución futura, incluidos el procesador, el vídeo, el audio, el mapeador, el registro de retención, la interrupción y el estado de temporización. Verifique que serializar y después restaurar reproduce la ejecución, no solo que los datos se pueden analizar. Exponga la memoria persistente mediante un callback claro o un límite de almacenamiento, en lugar de acoplar el núcleo a un único entorno anfitrión. Mantenga los controladores ordinarios como máquinas de estado sencillas, con transiciones explícitas de botones y protocolos serie. Modele los periféricos especializados mediante API específicas que conserven sus distintos comportamientos espaciales, temporales o de detección de luz. Tras una excepción de ejecución irrecuperable, establezca un estado de fallo explícito e impida que continúe la ejecución de fotogramas. Exija un reinicio o una recarga del programa documentados para recuperarse, en vez de continuar desde un estado parcialmente modificado. Mantenga estables las entradas de programa aceptadas y los tipos de callback públicos. Mantenga las declaraciones de tipos públicos junto con la implementación para que los consumidores de navegador y servidor observen el mismo contrato de API. ## Genera los archivos solo con la build e informa de lo que quedó sin probar Genere los paquetes de distribución, los archivos minificados, los mapas de código fuente y las declaraciones mediante la compilación aprobada. No edite directamente las salidas generadas. Verifique todos los objetivos de ejecución y formatos de módulo que el proyecto afirma admitir. La integración continua debe ejecutar los mismos controles de formato, linting, compilación, tipos y pruebas que se exigen localmente. Antes de cambiar el comportamiento del hardware, consulte especificaciones autorizadas y notas de implementación fiables. Documente junto a la operación afectada el motivo del código que no resulte evidente, incluida la consecuencia observable de cambiar su orden. Revise la diferencia final para detectar ediciones accidentales de archivos generados, documentación pública obsoleta, rutas de temporización no probadas y tareas de limpieza no relacionadas. Informe de las comprobaciones específicas ejecutadas, los resultados de rendimiento cuando correspondan, los fallos conocidos y cualquier ruta de hardware que siga sin verificarse.