A riesgo de romper un poco el hilo del desarrollo del cargador, voy a hacer unos pequeños "incisos" y desvíos para que sepamos un poco como funcionan las cintas.
Simplificando, hay dos lineas de conexión entre la cinta y los chips del Amstrad. Una es para el motor. El Amstrad le dice a la cinta cuando puede encenderse (suponiendo que el "PLAY" está pulsado) y cuando pararse.
La otra linea es de entrada/salida. Si la cinta está en modo "PLAY", le envía la información del sonido al Amstrad. El Amstrad puede enviarle igualmente la información a la cinta, que solo guardará si tenemos pulsado el REC.
La información de la cinta, que es principalmente una onda de sonido, podríamos decir que es el valor de la amplitud de la onda en el tiempo, es simplificada a un solo bit. La onda puede ser positiva o negativa.
Sería algo así como una "onda cuadrada", o simplificada a ello. En la realidad tal onda no puede representarse en un medio como una cinta, así que sufre algunas deformaciones, pero nada importante.
A todos nuestros efectos, no nos importa tanto la forma de la onda, como el tiempo en que el valor de la onda es positivo o negativo (bit 1 o 0).
Para representar información, lo que se hace es medir el tiempo en que dicha onda tiende a cambiar de signo.
Esto es, como si se tratara de un morse, "punto" y "raya". Un punto es una duración de bits 1 y 0s. Una raya es otra duración diferente de 1 y 0s. Esto es porque por temas de las ondas de sonido, no puede representarse un estado de bit 1 demasiado largo, ya que requiere una frecuencia más allá de las capacidades de la cinta.
Así que jugamos con intervalos válidos. Lo que medimos es un ciclo de 1s y 0S.
Digamos que si un ciclo de 1 y luego 0 son 600 ciclos de reloj, y a dichos ciclos le asignamos un valor de BIT 0, al bit 1 consideramos que sería la mitad de tiempo. Digamos que 300. Usaríamos el punto frontera (450) para determinar si un ciclo es un 1 o un 0. Y si fuera alarmántemente grande (Ej. más de 2000) consideraríamos que el sonido "se ha cortado" y que ese bloque de datos ha finalizado.
La rutina estandar carga del AMSDOS funciona aproximadamente así.
Espera un tiempo a "escuchar" ciclos siempre de la misma frecuencia (dentro de un intervalo). Las cintas no son precisas.
Podría obtener 400, 389, 412, 399, 403, 405, 397... Va calculando una "media" para hacerse una idea de la frecuencia (los baudios) en la que se está transmitiendo un bloque.
Para el AMSDOS, durante esa fase que se llama "sincronización", se considera que este valor es el que representa al bit 1, mientras que el bit 0 (más probable cuando hay datos vacios) se usa un pulso de la mitad de duración que el bit 1.
Esta forma de condificar tiene una gran ventaja, y es que permite usar la misma rutina independientemente de la velocidad de referencia. Puedes cargar igual a 1000, 1500 2000 baudios, etc. etc.
Hace más tolerante a la cinta, ya que no todas son exactas. Una cinta más lenta podría leer una cinta de 1000 baudios como si fuera de 950, solo porque el motor es un poco más lento de lo que debería o la cinta es más tensa de lo esperado. Pero no es problema, ya que ese cambio de velocidad afecta por igual a los bits 1 y 0.
Otros cargadores implementados en otras computadoras o en ensamblador, usan velocidades de refenrecia fijas, y eso los hace más intolerantes a cambios en la velocidad.
Una vez que ha obtenido un mínimo de pulsos y estos se mantienen en un patrón regular, él espera la llegada de un bit 0, que representa el fin de la sincronización.
Despues de eso, le sigue un byte de identificador de bloque. Un número arbitrario que se usa para distinguir entre los bloques que se usan de cabecera (nombre de archivo, número de bloque de archivo, tipo de archivo, etc... Los que se leen y se usan para poner mensajes en "Loading...") y los de datos.
A estos "bloques", para que no nos confundamos, los vamos a llamar "Bloques Turbo". Estos "Bloques Turbo" en los archivos TZX/CDT se representan con una entrada del tipo "Turbo Speed Data Block".
Los archivos AMSDOS estandar se dividen en trozos de datos de 2KBytes máximo.
Cada trozo lleva dos "Bloques Turbo".
Uno representa la cabecera. Contiene el nombre del archivo, tipo, posición de carga por defecto (se puede sobreescribir en el comando para binarios), posición de arranque que se usará si se carga con RUN", longitud a efectos de archivo (independientemente de como va en la cinta), número de bloque, si es el primer bloque, si es el último bloque y no debe cargar más, etc. etc.
En la definición de TZX, no existe ese byte de sincronización que existe en AMSDOS, así que para el CDT, es el primer byte de datos que contiene dicho bloque. Si con CDTMaster observais dicho Byte, vereis que los bloques para cabecera, tienen un byte presincronización (el primer byte de datos) = 44 (0x2C), mientras que los bloques turbo de datos se indican con 22 (0x16).
Luego, otra cosa que podreis observar, es que los datos se guardar siempre en subloques de datos de 256 bytes.
Cada subbloque va seguido de dos bytes que representan un CRC-16 de los datos de dicho bloque.
Así, aunque el archivo tenga una longitud de 50 bytes, lo que salvará el AMSDOS es.
Dos bloques TZX de 259 bytes (más alguno extra que carece de importancia, solo como garantía de que el último byte es interpretado bien).
Esto es, un byte de identificación (0x2C o 0x16)+ subbloque de 256 + 2 CRC.
El primero 0x2C y contiene los datos de la cabecera
El segundo 0x16 con los datos del archivo. A pesar de que el archivo tiene 50 bytes, se rellenará con un grupo de bytes (normalmente 0) para completar un bloque de 256 bytes y luego se hace el CRC, contando incluido con dichos bytes de relleno.
Eso sí, a efectos de carga, en memoria solo trasladará esos 50 bytes. El resto solo se procesarán para calcular el CRC final y saber si los 50 bytes + relleno coinciden con el código de comprobación CRC.
Así pues, a nivel de cinta, ocupa lo mismo un archivo de 1 byte que uno de 256, porque siempre se rellena a bloques de 256 bytes. Eso sí, si ocupara 257, entonces incluiría dos bloques, el primero para los primeros 256 y el segundo el byte que falta más 255 más de relleno. Más CRCs y tal...
La función CAS READ (&BCA1) del firmware nos permite leer "Bloques turbo" acordes a esta forma de codificación. Eso sí, sin colores ni nada.
¿Por qué todo este rollo? Porque vamos a usar esta función CAS READ para leer nuestros bloques como ejemplo, ya que el cargador en ensamblador por el que luego daremos el cambiazo
lee bloques en el mismo formato, así que es tan simple cambiar la llamada a CAS READ, por el fragmento de nuestro cargador "Karnov" modificado. Copiar y pegar.
Pero antes de nada, necesitamos una cinta que cargar. Así que volvemos a CDTMaster a nuestro disco, para convertirlo en bloques para la función "CAS READ". (Recuerda asegurarte de que los emuladores no estén usando la misma imagen de disco o CDTMaster no podrá abrirlo).
Si teníais CDTMaster iniciado, mejor cerrarlo y abridlo de nuevo para partir de los paneles limpios.
Abrimos igual que antes la imagen de disco, y nos dirigimos al archivo PANTALLA.BIN.
Antes de convertirlo, por curiosidad, podeis fijaros en la información del panel.
Ved que la posición de carga "Load Position" es de 0xC000 (indicado en decimal en la zona editable, en hexadecimal al lado). Justo la posición de memoria de la pantalla en situación estandar.
Le damos a convertir a TZX como antes. Pero esta vez, en las opciones de conversión, vamos a indicar algo diferente.
En vez de la opción de antes, vamos a poner en la opción "Maximum length for
first block" 65535.
Esto está fuera del rango indicado (hasta 2048) pero nos permite obtener el bloque de datos.
Dado que no lo vamos a cargar con LOAD sino con la función "CAS READ" que puede cargar bloques turbo directamente, podemos...
debemos convertirlo en un solo bloque.
Y también, porque vamos a forzar un poco la carga, vamos a poner como velocidad 3000 baudios.
Echemos un vistazo a la pestaña de CDT/TZX Editor.
Esta vez, en el panel de la derecha veremos solo dos bloques TZX, tal y como esperábamos.
Uno de la cabecera, pequeño y otro de 16515 bytes.
Este es el que nos interesa.
Si hacemos doble click sobre dicho bloque, nos desplega una nueva pantalla.
Si pulsamos "Edit Data", nos pasa a un editor hexadecimal.
Tal y como esperábamos, el primer byte a nivel CDT, que es, a nivel AMSDOS, el byte de Identificación de bloque turbo, es "16" (hex) que representa un bloque de datos.
CAS IN READ nos permite especificar el tipo de bloque, y puede ser cualquier byte. Vamos a cambiar este, para que no sea coincidente con los estándares para archivos. Vamos a poner, por ejemplo, 54 para la pantalla, y 55 para el juego (CHICHEN1.BIN).
Se edita directamente en el hexadecimal, y pulsamos (botón abajo) "Save" y luego sobre la pantalla anterior "Accept".
Este bloque lo copiamos a la parte izquierda como la vez anterior, con Control+C en el panel derecho y Control+V en el izquierdo.
Podemos borrar, si queremos no liarnos, los bloques del panel derecho, seleccionándolos y pulsando "delete" (sí, por ahora solo hay atajos de teclado que hay que saberse
Volvemos a la pantalla "AMSDOS Files" y escogemos CHICHEN1.BIN
Esta vez es importante fijarnos en la posición de carga y arranque, porque son totalmente dependientes del juego.
En CHICHEN, la posición de carga y la de ejecución han coincidido, pero no tendría por que ser así.
Es 0x0840
Repetimos operación.
Convertimos, un solo bloque, 3000 baudios, y en la pestaña CDT/TZX Editor, editamos bloque y ponemos el primer byte a 55 tal y como hemos planteado.
Copiamos y pegamos al panel derecho.
Y salvamos a "Chi1test.cdt". La cinta NO está completa, pero nos servirá para las pruebas.
Seguimos en otro post