Como en muchas otras cosas, MicroHobby también nos puede dar un curso de programación de transfers. En este caso, el que nos interesa es el artículo sobre el
Transfer para +3 que modifica el pokeador automático para que funcione en +2A/+3 y además incluye un programa de transfer para 128k (el enlace es a la primera página del artículo, la 42).
En cuanto a los problemas propios de un 128k el principal es "adivinar" la página que está metida. En este caso, el autor hace (más o menos) lo que tú dices: primero suma todos los bytes de la página actual y luego va sumando una por una todas las páginas hasta encontrar una suma que le coincida. La rutina va desde la línea 2480 hasta la 2680, usando la subrutina DETEC (página 44, desde la línea 70 a la 210) para la suma. La suma de 16 bits es más segura, pero también se podría usar una de 8 bits o un XOR para ahorrar algún byte. Aún así, quedan fuera los casos "raros" (modos allram de los +2A/+3).
(Como decías, una forma mejor sería usar una función hash o un CRC... pero creo que complicaría bastante el código además de que la ejecución sería más lenta)
Una vez que sabemos cuál es la página, ya solo nos queda elegir un formato y escribir las rutinas de carga y grabación. En mi caso, usaría un formato parecido a esto:
- BASIC
- CODE de casi todo el loader
- SCREEN$ (incluye última rutina de carga y la de restauración)
- 7 bloques de 16384 bytes con las páginas 0, 1, 2, 3, 4, 6 y 7.
- Bloque de 9472 bytes que incluye las direcciones 23296 a 32767.
El bloque CODE puede ir en cualquier dirección a partir de 24576, siempre que no llegue a 32768 (porque lo sobreescribiríamos al leer la página 2). Este bloque debería cargar el SCREEN$ y los 7 bloques de 32768 (¡siempre con las interrupciones deshabilitadas!
*). Al terminar, metemos la página que queremos y saltamos a la rutina de restaurar registros.
En caso de hacer un mantransfer v4, esta rutina sería casi la misma que la del mantransfer v3... simplemente cambiamos el bloque a cargar (desde 23296, con 9472 bytes de longitud) y el resto sigue igual... salvo que quieras enfrentarte al siguiente problema específico de los 128k: los registros del AY.
(En este caso, creo que los registros del AY sí que son de lectura/escritura por lo que incluir una rutina que los grabe y otra que los restaure no es demasiado complicado)
Hacer el programa del transfer no es demasiado complicado, lo jodido es hacerle sitio en la ROM.
La opción más válida es usar un dispositivo que pagine su propia ROM, siendo lo más deseable que se pueda desactivar esa paginación para no comprometer las funciones del spectrum
**.
O, si estamos programando un emulador y queremos que suelte snapshots en formato tap, la siguiente opción sería hacer trampa a lo bestia y simular el comportamiento del transfer desde el emulador. Tenemos la ventaja de que conocemos el estado exacto de la CPU, puertos del Spectrum y registros del AY... no tenemos que hacer operaciones raras para averiguar de modo indirecto algo que ya sabemos
***
* La rutina de interrupción del Spectrum +3 decrementa un contador en la página 7. Si mal no recuerdo, esto provocó que tuvieran que retocar
el cargador del Ninjajar!.
** Si nos ponemos a diseñar hardware, podríamos poner esto en la lista de deseos:
- Que el hardware almacene los últimos bytes enviados a determinados puertos ($FE, $1FFD y $7FFD). Así no hay que hacer el gambas para poder averiguar cómo está la paginación (y podemos soportar los modos all-ram y el color del borde).
- Que el hardware pueda activar/desactivar la paginación de la ROM a voluntad (p.ej.: paginar cuando se pulse NMI y despaginar al hacer un out a un determinado puerto).
- Ponerle algo de RAM que posibilite hacer snapshots sin corromper la pantalla.
*** O también podemos coger el diseño que he descrito antes e incorporarlo al emulador como algo virtual. De nuevo, podemos hacer todas las trampas que queramos... sabemos exactamente el estado de la CPU.
I have traveled across the universe and through the years to find Her. Sometimes going all the way is just a start...