Conexión de un C64 a Internet

Otra novedad bastante impresionante es la posibilidad de conectar un C64 a una intranet con protocolo Ethernet y, a través de ella, a Internet.

El VIC-20 y el C64 ya disponían de módems. Se trataba de dispositivos que, usando la red telefónica convencional y diferentes modulaciones, permitían conectar estos equipos a BBS’s y otros servicios en línea similares.

Modem

Sin embargo, Internet se popularizó en España en torno al año 1995 y, a esas alturas, Commodore International ya había desaparecido (desapareció en 1994). Es decir, que Internet, o al menos la popularización de Internet, es posterior al C64, que es de los años 80 y primeros 90.

Sin embargo, hoy en día se han desarrollado dispositivos que, bien usando el puerto de usuario, bien usando el puerto de expansión, permiten conectar un C64 a una intranet basada en Ethernet. Y puesto que muchas intranets están conectadas a Internet a través de un router, esto permite conectar un C64 a Internet.

Aunque no los he probado, al menos tengo referencias de estos dos dispositivos:

Internet

Lógicamente, un C64 no puede consumir los contenidos típicos de Internet: páginas web, fotos, vídeos, ficheros de música, aplicaciones en línea, etc. El hardware y el software son tan limitados que no lo permiten. Pero lo que sí puede consumir es contenidos adaptados al C64.

Y esto es, precisamente, lo que ofrecen páginas como CommodoreServer.com. En esta página se ofrecen servicios de subida y descarga de imágenes D64, tanto a espacios públicos como privados, juegos multiusuario en línea, chat en línea con otros usuarios, etc. Para ello, la página definió el protocolo CSIP (Commodore Server Internet Protocol), un protocolo de la familia TCP/IP orientado a la prestación de servicios y contenidos para el C64.

Algunos de los servicios de CommodoreServer.com no sólo pueden usarse desde un C64 físico con una conexión a Internet. Muchos de ellos pueden usarse también desde un PC con el emulador VICE. Y además también hay servicios complementarios en formato web convencional.

Imágenes T64 y D64; dispositivos SD2IEC

Aunque en la entrada anterior hemos dicho que no estamos especialmente interesados en los tipos de periférico del C64, ni en su uso práctico, lo cierto es que en los últimos años sí ha habido algunos desarrollos que, por su utilidad, merece la pena comentar.

En primer lugar, están las imágenes T64 y D64. Una imagen es un fichero de PC o similar que contiene una copia bit a bit de un dispositivo, por ejemplo, de un disco duro.

En el caso de las imágenes T64 estamos hablando de ficheros de PC que contienen una copia bit a bit de una cinta del C64 (la “T” viene de tape). Y en el caso de las imágenes D64 estamos hablando de ficheros de PC que contienen una copia bit a bit de un diskette (la “D” viene de diskette).

Tanto una cinta como un diskette del C64 podían contener varios ficheros o programas (normalmente en formato PRG), no solamente uno. Por tanto, hoy en día tenemos la comodidad de poder manejar en un fichero de PC todo el contenido de una cinta o de un diskette.

Se pueden descargar ficheros T64 y D64, y también ficheros PRG sueltos, de muchos sitios de Internet dedicados al C64, como por ejemplo Gamebase64 (http://gamebase64.com/) o The C64 Scene Database (https://csdb.dk/). Lógicamente, si lo hacemos debemos ser respetuosos con los derechos de autor, si bien en muchos casos se trata de software olvidado y/o desarrollado por empresas que ya no existen. Es más, gracias a sitios como estos se han podido conservar.

Los ficheros T64 y D64, es decir, el contenido de las cintas y discos que representan, se pueden cargar en VICE con la opción “Autostart disk/tape image” del menú “File”. Es más, con esta opción se puede explorar el contenido de una imagen antes de usarla:

Imagenes y VICE

Por último, están los dispositivos SD2IEC. Estos dispositivos, como indica su nombre, hacen de puente (de ahí el “2” o “to”) entre sistemas de almacenamiento modernos, por ejemplo, tarjetas SD, y conexiones antiguas, por ejemplo, la conexión IEC o puerto serie del C64, que es la que se utilizaba para la disquetera.

De este modo, es posible guardar en almacenamiento moderno, de mucha más capacidad y velocidad, muchos diskettes del C64. Parece mentira, pero en una tarjeta SD actual (¿128 GB?) pueden caber muchos miles de diskettes de 170 KB.

SD2IEC

Entrada/salida

Por entrada/salida, E/S, o I/O en inglés, se entiende el intercambio de información entre el ordenador, el C64 en nuestro caso, y el mundo exterior. Cuando la información entra en el ordenador se habla de “entrada”, y cuando sale se habla de “salida”.

La entrada/salida normalmente requiere la conexión al ordenador y el uso de dispositivos periféricos. En el caso del C64 los periféricos más habituales son:

  • TV o monitor tipo CRT (tubo de rayos catódicos).
  • Datasette.
  • Unidad de diskette.
  • Cartuchos.
  • Joysticks.
  • Paddles.
  • Impresoras.
  • Modems.
  • Etc.

Periféricos

No obstante, en ocasiones también se utiliza el C64 para conectarlo a circuitos electrónicos desarrollados a media, por ejemplo, sensores o sistemas de control. Recuerdo que, cursando la EGB hacia la mitad de los 80, en mi colegio nos llevaron de visita a una fábrica conservera cuyo sistema de producción estaba controlado por … ¡¡un VIC-20!! Increíble, pero totalmente cierto. Doy fe.

La conexión del C64 a los dispositivos periféricos es mediante los “puertos”. Esta palabra resulta un poco ambigua porque, como veremos más adelante, también se utiliza para designar las posiciones de memoria que utiliza el microprocesador (6510) para leer/escribir de los dispositivos. Por ello casi prefiero hablar de “interfaces” o “conexiones”.

Las interfaces o conexiones del C64 son:

  • Puertos de control.
  • Puerto de expansión.
  • Puerto de usuario.
  • Puerto del datasette.
  • Puerto de vídeo.
  • Puerto de RF.
  • Puerto serie.

Interfaces

Cuando la comunicación entre el C64 y el periférico es bit a bit se habla de entrada/salida en serie, y cuando tiene lugar mediante varios bits a la vez, normalmente de ocho en ocho, se habla de entrada/salida en paralelo. El puerto serie permite entrada/salida en serie; el puerto de usuario permite entrada/salida en paralelo.

El propio teclado se puede considerar un periférico de entrada, aunque su conexión con el C64 es interna, no externa, y, por tanto, no se puede ver salvo que se abra el equipo.

Teclado

La comunicación del microprocesador con los periféricos o dispositivos electrónicos conectados a las interfaces no es directa, sino que en muchos casos es a través de unos chips especiales llamados 6526 CIA – Complex Interface Adapter. El C64 tiene dos CIAs, llamados CIA1 y CIA2.

Resumiendo mucho, lo que hacen estos chips es servir de interfaz entre el microprocesador y los periféricos o dispositivos. Gracias a ellos, el microprocesador ve y trabaja con unas posiciones de memoria llamadas “puertos” (obsérvese la ambigüedad con la otra acepción de puerto). Estos puertos se puedan manejar con instrucciones “lda” y “sta” igual que cualquier otra posición de memoria. Además, estos chips tienen capacidades de temporización muy útiles, es decir, permiten definir relojes, cronómetros, y similares.

Dado que en este blog estamos especialmente interesados en la programación en ensamblador, y no tanto en describir los tipos de periféricos y su uso práctico, más adelante nos centraremos en cuáles son los registros del CIA1 y del CIA2, y cómo hacer algunos programas de E/S y temporización.

Ficheros SID

El SID fue un chip muy avanzado para su época. Ya hemos comentado sus características: tres voces independientes, varias formas de onda, filtros, etc. Esto hizo que la música del C64, típicamente la de sus juegos, fuera superior a la de sus competidores. Y no sólo eso, también fue superior a la de algunos equipos que vinieron después, como los primeros PCs, que apenas tenían un altavoz interno con capacidad para emitir algunos pitidos.

Todo esto hizo que hubiera auténticos forofos de la música del C64. Y algunos llegan hasta hoy, ya que hay varias iniciativas en Internet para recopilar y conservar música del C64. Algunos, incluso, hacen “remixes” de piezas SID (ver http://remix.kwed.org/ o https://www.remix64.com/). Para mi gusto esto último ya es demasiado… 🙂

Una de las iniciativas más destacadas es High Voltage SID Collection, que es una página web y base de datos de ficheros SID. Esta página permite descargar la colección completa (más de 50.000 títulos), buscar piezas en función de sus metadatos (ej. título, autor, año de publicación, etc.) y descargarlas en formato SID, descargar reproductores SID, visitar páginas relacionadas con el C64, etc.

Hardball

Un fichero SID es un fichero que, curiosamente, no sólo contiene la información musical de la pieza que hemos visto en entradas anteriores (ej. octavas, notas, duraciones, volúmenes, etc.) Además, contiene código máquina del C64 para inicializar el SID y reproducir la pieza.

Por tanto, hay dos formas principales de reproducir un fichero SID:

  • Cargándolo en un reproductor multimedia, por ejemplo, de PC o MAC, con capacidad de reproducir ficheros SID. Algunos reproductores tienen esta capacidad de forma nativa, y otros requieren algún tipo de plug-in. Hay muchos ejemplos de reproductores bajo la sección “SID PLAYERS” de HVSC.
  • Incluyéndolo en algún programa en ensamblador, por ejemplo, con la directiva “incbin” de CBM prg Studio. Habrá que incluir el fichero en la dirección indicada (en el caso de arriba $7000), inicializar el SID con la dirección indicada (en el caso de arriba con «jsr $7c30»), y reproducir la pieza también con la dirección indicada (en el caso de arriba con «jsr $7c33»).

A continuación, un ejemplo de reproducción con TinySID:

Commando.PNG

Respecto a la segunda opción, la de incluir un fichero SID en un programa en ensamblador, hay que tener en cuenta que, en función del diseño del programa, la ubicación en memoria del fichero SID podría no resultar adecuada. Para tales situaciones, hay programas que permiten modificar el fichero SID para moverlo a otra posición de memoria. Es el caso de Sidreloc.

Utilizando ficheros SID descargados resulta realmente fácil añadir música y efectos a nuestros programas en ensamblador. Esto puede verse en el programa de ejemplo.

Y a partir de ahora, entrada/salida…


Programa de ejemplo: Prog54

Duración y volumen

En la entrada anterior hemos visto cómo guardar en una tabla la información de la melodía, es decir, la secuencia de notas con sus octavas. Si en vez de tener una melodía simple, tuviéramos una melodía con dos o tres voces, sería suficiente con que la tabla fuera de doble o triple entrada.

Además de lo anterior, hemos visto cómo leer la tabla, convertir la información de octavas y notas a frecuencias (consultando una tabla de frecuencias para la octava 7 y dividiendo la frecuencia obtenida por dos N veces), y cómo programar el SID con las frecuencias.

El esquema anterior (guardar la información musical en una tabla) se puede extender también a la duración de las notas y su volumen. De esto nos ocupamos en esta entrada.

La duración de las notas es el tiempo que transcurre desde que empieza la fase “attack” hasta que termina la fase “release”:

ADSR

La fase “attack” empieza cuando se activa el bit 0 del registro VCREG1/2/3. La fase “release” empieza cuando se desactiva ese mismo bit 0, y termina tras la duración de esa fase (recuérdese que el parámetro “release” es un tiempo).

Por tanto, podemos controlar la duración de la nota controlando el tiempo desde que activamos el bit 0 del registro VCREG1/2/3 hasta que lo desactivamos. Esto se puede hacer con una rutina de retardo. Y la duración de cada nota se puede registrar en una nueva entrada de la tabla ya descrita anteriormente.

Sin ser experto en música, supongo que musicalmente no será necesario que las tres voces estén sincronizadas. Es decir, supongo que es perfectamente posible que una voz y otra cambien de nota en momentos diferentes. Sin embargo, desde el punto de vista de la programación, esto complicaría mucho el programa, y más en un ordenador como el C64 que sólo tiene un hilo de ejecución (interrupciones aparte).

Por todo ello, supondremos que las tres voces del C64 van sincronizadas, es decir, empiezan a la vez, y cambian de una nota a la siguiente en el mismo instante. O, lo que es lo mismo, las duraciones de las sucesivas notas tienen que ser las mismas para las tres voces.

En definitiva, será suficiente con añadir una cuarta columna a nuestra tabla de triple entrada, que ahora pasará a ser de cuádruple entrada:

Tabla melodía triple.PNG

La duración de las notas no se suele expresar en términos absolutos (por ejemplo, «una negra equivale a un segundo»). Más bien, se suele expresar como una proporción de un compás. De este modo, si el compás es de 4/4, las duraciones son:

  • Redonda = 4/4
  • Blanca = 2/4
  • Negra = 1/4
  • Corchea = 1/8
  • Semicorchea = 1/16
  • Fusa = 1/32
  • Semifusa = 1/64

Duración notas

Desde el punto de vista de la programación, dado que vamos a usar una rutina de retardo para controlar la duración (básicamente un bucle), lo más práctico es que la rutina haga más o menos iteraciones en función del tipo de nota. Y puesto que nos interesa no complicar mucho más la tabla anterior, lo más práctico sería algo así:

  • Redonda = 16 iteraciones.
  • Blanca = 8 iteraciones.
  • Negra = 4 iteraciones.
  • Corchea = 2 iteraciones.
  • Semicorchea = 1 iteración.
  • Fusa = prescindir.
  • Semifusa = prescindir.

De este modo, dedicando el nibble alto de la cuarta entrada a la duración es suficiente, y podemos dedicar el nibble bajo al volumen. Por tanto, tenemos que prescindir de fusas y semifusas en aras de mantener la tabla lo más sencilla posible.

Y con el volumen ya hemos dejado caer lo que va a pasar. El volumen es común para las tres voces (bits 0, 1, 2 y 3 del registro SIGVOL). Y sólo puede tomar los valores 0 – 15. Por tanto, perfectamente podemos almacenarlo en el nibble que deja libre la duración (nibble bajo).

En conclusión, si complicamos el programa de ejemplo de la entrada anterior, de modo que, además de las octavas y notas para las tres voces, también estén en la tabla (que pasa a tener cuatro entradas) la duración y el volumen, ya tenemos todo resuelto. Además de leer y configurar las frecuencias de las diferentes voces, tendremos que leer y configurar el volumen, y mantener las voces activas durante el tiempo indicado, cambiando entonces a la siguiente nota.

Un último apunte de interés es que, en cuanto las melodías tengan unas pocas notas, la tabla superará las 256 posiciones de memoria. Por tanto, es probable que el modo de direccionamiento indexado se nos quede corto, y tengamos que usar el modo de direccionamiento indirecto – indexado.


Programa de ejemplo: Prog53

Octavas, notas y frecuencias

Una octava es el rango de frecuencias que va desde una frecuencia hasta el doble de esa frecuencia. En una octava caben ocho notas: do, re, mi, fa, sol, la, si y do, que ya sería la primera nota de la siguiente octava.

Octava

Una nota, por su parte, se caracteriza por una frecuencia y una duración: redonda, blanca, negra, corchea, semicorchea, fusa y semifusa.

Duración notas

Las frecuencias correspondientes a cada nota pueden consultarse en el apéndice E del libro “Commodore 64 Programmer’s Reference Guide” (ver página 384). Aquí se reproduce sólo la primera octava (octava 0) y el comienzo de la segunda (octava 1):

Nota – octava Frec. decimal Frec. hex. high Frec. hex. low
C-0 268 $01 $0C
C#-0 284 $01 $1C
D-0 301 $01 $2D
D#-0 318 $01 $3E
E-0 337 $01 $51
F-0 358 $01 $66
F#-0 379 $01 $7B
G-0 401 $01 $91
G#-0 425 $01 $A9
A-0 451 $01 $C3
A#-0 477 $01 $DD
B-0 506 $01 $FA
C-1 536 $02 $18
C#-1 568 $02 $38

Esta tabla utiliza la notación musical inglesa, que tiene esta correspondencia con la notación musical tradicional :

  • Do = C.
  • Re = D.
  • Mi = E.
  • Fa = F.
  • Sol = G.
  • La = A.
  • Si = B.

Es decir, según esta tabla C-0 es do de la octava 0, C#-0 es do# (sostenido) de la octava 0, C-1 es do de la octava 1, C#-1 es do# (sostenido) de la octava 1, etc. Así desde la octava 0 hasta la octava 7. Es decir, el SID maneja frecuencias para un rango de ocho octavas.

Y como se decíamos en la entrada anterior, lo lógico es que el programa que reproduce la melodía no esté programado en términos de frecuencias, sino que esté programado en términos de notas, ya que así es como componen los músicos. De este modo, usando la tabla anterior de conversión de notas a frecuencias el programador puede pasar fácilmente de notas a frecuencias, y programar el SID con las frecuencias.

En realidad, ni siquiera es necesario que el programa maneje la tabla anterior completa (12 notas por octava x 8 octavas = 96 notas). Sabiendo que una nota (ej. C-0) tiene una frecuencia (ej. 268) y la misma nota en la siguiente octava (ej. C-1) tiene el doble de frecuencia (ej. 536), es suficiente con manejar una tabla en memoria con la información de la octava 0, obtener una frecuencia base a partir de la nota, y multiplicar esa frecuencia por 2, 4, 8, 16, 32, 64 o 128 en función de la octava.

Análogamente, también nos valdría manejar una tabla en memoria con la información de la octava 7, obtener una frecuencia base a partir de la nota, y dividir esa frecuencia por 2, 4, 8, 16, 32, 64 o 128 en función de la octava.

En realidad, la opción de dividir es más conveniente que la de multiplicar, ya que evita problemas con los redondeos y permitiría incluso introducir silencios (tiempos en que no suena ninguna nota) llegando a dividir la frecuencia base por 256.

En resumen, nuestro programa necesitará dos tablas:

  • Una tabla de conversión de notas a frecuencias para la octava 7.
  • Una tabla con la información de notas y octavas de la melodía. En realidad, hará falta una tabla de este tipo para cada una de las voces (1, 2 o 3 voces). Eso, o una tabla de triple entrada, que es equivalente.

Gráficamente, el proceso será como sigue:

Notas y frecuencias.PNG

La tabla con la melodía (o tablas; hasta tres, una por voz) puede diseñarse de muchas maneras. No obstante, dado que el SID soporta ocho octavas (0-7) y doce notas por octava (0-11), es suficiente con reservar un nibble para especificar la octava (16 valores posibles; se usarán sólo 8) y otro nibble para especificar la nota (16 valores posibles; se usarán sólo 12). De este modo, con un byte por nota (incluyendo su octava) es suficiente.

El fin de la melodía puede marcarse, por ejemplo, con el valor $ff, puesto que $f no es un valor válido para la octava (máximo 7) ni para la nota (máximo 11).


Programa de ejemplo: Prog51
Programa de ejemplo: Prog52 (ampliación a 3 voces)