Yo de verdad que quiero ponerme con el interfaz de usuario...Pero en la lista de cosas que quería para el cartucho, estaba una cosa que cuando leí sobre ello, pensé que era imposible..Pero ahora...igual...es posible, y es el meter KERNALs alternativos como hace EF3 y la 1541ultimate.
Esta "cosita" no es *nada* trivial. El documento que lo explica es éste:
http://skoe.de/kernal/kernal-cartridge.pdfA ver si soy capaz de explicarlo en cristiano...
Cuando se mete un cartucho "simple" en el C64 (con una ROM que contiene un juego), el cartucho utiliza 2 pines del puerto de expansión, para "decirle" al C64 en qué zona de memoria debe mapear la ROM que contiene.
Estos pines son GAME y EXROM, y dependiendo de si el cartucho los pone a OV o no, se tienen 4 combinaciones:
GAME EXROM
1 1 No hay ninguna rom que mapear.
1 0 Cartucho de 8KB, mapeado entre $8000..$9FFF
0 0 Cartucho de 16 KB mapeado en 2 bloques , $8000..$9FFF y $A000..$BFFF
0 1 Cartucho de 16 KB mapeado en 2 bloques, $8000..$9FFF y $E000..$FFFF
Mientras los 3 primeros modos no afectan al resto de la memoria,
el último modo, llamado "ultimax" (modo de compatibilidad con el Commodore MAX), hace que una gran
parte de la RAM del C64 no esté accesible ( 2K de memoria disponible...), así que es muy raro que se use...
Pero en este modo, sí que es posible sobreescribir el KERNAL que usa el C64, ya que la ROM del cartucho se mapea a las direcciones usadas por el KERNAL ($E000-$FFFF)
Por otra parte, está que el C64 tiene, eso, 64K de RAM. Incluso si por defecto, parte de esa RAM está "oculta" porque hay una ROM en el mismo espacio de direcciones.
Si en $E000-$FFFF está el KERNAL (ROM), también hay una RAM en ese mismo espacio de direcciones. La PLA se encarga de que, por defecto, cuando se *lee*, se devuelva el contenido de la ROM, y cuando se *escribe*, se escribe en la RAM que hay "por debajo".
Pero desde programa, es posible cambiar todo esto: es posible hacer que la ROM sea "invisible", y que sólo se vea RAM.
Para esto, existen 3 bits en la posición $1 de "memoria": LORAM, HIRAM y CHAREN.
Por no liarlo más, de esos 3, si HIRAM está a 1, leer la parte de la memoria donde está el KERNAL, devolverá lo que hay en la ROM.
Si HIRAM está a 0, leer esa parte de memoria devolverá lo que hay en la RAM.
En ambos casos, escribir en esas posiciones, siempre es en la RAM.
La unión de HIRAM, LORAM (gestionados desde código) y GAME y EXROM (gestionadas por el cartucho), dan los diferentes modos de memoria del C64,
o sea, qué se "ve" en cada banco de memoria.
Esto también afecta al propio cartucho.Incluso si el cartucho establece GAME=1, EXROM=0 ,
si LORAM está a 0, lo que está mapeado en $8000-$9FFF, es la RAM del C64, no el cartucho.
Esto el cartucho lo tiene que tener en cuenta, para no intentar escribir nada en el bus de datos, si LORAM está a cero.
Quien debe escribir, es la RAM (y pasan cosas malas si 2 chips intentan escribir a la vez en el mismo cable).
De la misma forma, si HIRAM está a 0, lo que está mapeado en $A000-$BFFF, es RAM, no el bloque "alto" del cartucho (o el BASIC).
Es por eso que LORAM e HIRAM son 2 señales que el cartucho recibe. Aunque el cartucho reciba una dirección que corresponde a su banco de memoria, si LORAM está a 0, o HIRAM está a 0, debe considerarse "desactivado" y no hacer nada.
Pero hay que diferenciar los bits HIRAM/LORAM de las señales HIRAM/LORAM del puerto de expansión,
porque podría parecer que cuando se pone uno de los bits a un valor u otro, la señal en el puerto, cambia a ese valor.
No funciona así. HIRAM y LORAM del puerto de expansión, sólo se establecen cuando se intenta acceder a los rangos de direcciones asociadas al cartucho.
Y, no sólo eso, sino que la lógica es "inversa": Cuando el bit HIRAM está a 1, el pin HIRAM del puerto de expansión, está a 0.
Por ejemplo:
- Si hay un acceso a la posición $100 , como no pertenece a ningún bloque del cartucho, los pines LORAM y HIRAM estarán a "1", independientemente de lo que haya en los bits LORAM y HIRAM.
- Si hay un acceso a la posición $8100, y el cartucho tiene GAME y EXROM a cualquier cosa que no sea 1/1, el pin LORAM estará al nivel "contrario" que el bit LORAM.
El hecho de que estos pines sólo se establezcan cuando se accede al cartucho, es importante más tarde..
Entonces, para poder meter un KERNAL diferente en un cartucho, tenemos que:
-Hay que utilizar el modo ultimax.
-Si el bit HIRAM está a 1, el cartucho debe devolver el byte correspondiente de la ROM.
-Si el bit HIRAM está a 0, el cartucho no debe hacer nada.
Vale, supongamos por ahora que lo del modo ultimax no es problema.
Hay que saber si el bit HIRAM está a 1 o a 0, para saber si el KERNAL es visible, o no.
Cómo es posible saberlo?
Lo podríamos saber cuando la CPU pidiera una dirección al cartucho..
Pero lo que se quiere es cambiar el KERNAL, que está en un rango de memoria distinto (a menos que el C64 estuviera en modo "ultimax", pero no queremos estar en ese estado)
por lo que los accesos al rango $E000-$FFFF, no establecen el pin HIRAM del puerto de expansión..
Otra opción sería "espiar" el puerto de direcciones y de datos. El cartucho siempre puede estar "leyendo" del bus, "espiando" todo lo que pasa por él. Si detecta que se está escribiendo
en la posición $1, podría leer el dato que se está escribiendo, y ver qué está activado...
El problema con esto es que esa posición $1...No está en la RAM. La posición $1 de memoria, está dentro del propio procesador. La dirección de memoria ($1), sí que es visible en el bus de direcciones.
Pero el valor que se escribe en esa posición $1, no.
Entonces, es posible saber que ha cambiado el mapa de memoria.
Pero mientras la CPU no quiera leer del cartucho, no se puede saber a qué ha cambiado.
(Ojo, que, además , el cartucho tiene que aparentar "no existir".Tiene sólo que reemplazar el KERNAL, cuando se llama al KERNAL. EL resto del tiempo, debe actuar como si no existiera, o sea, GAME=1, EXROM=1..Por lo que la CPU no va a leer nunca del cartucho, ni cambiar los pines LORAM/HIRAM ...)
Solución: *forzar* a que se lea del cartucho.
La forma de conseguirlo, es:
- El cartucho no establece, inicialmente, ni GAME, ni EXROM. Como si no estuviera.Simplemente, está mirando el bus de direcciones para detectar cualquier acceso a $1.
- Cuando detecta que se ha accedido a $1, sigue espiando al bus, esperando esta vez a que se intente acceder al KERNAL , o sea, una dirección en el rango $E000-$F000
- Todo lo siguiente, debe ocurrir en el mismo ciclo de reloj (en realidad, medio ciclo):
- Detectar que se va a acceder al KERNAL.
- Si es así, se disponen de muy poquitos nanosegundos para:
- Poner GAME y EXROM a 0 (Y, de pronto, aparecer como un cartucho de 16KB conectado al C64)
- FORZAR un 0 en la línea 14 del bus de direcciones. Esto hace que la dirección pase de estar en el rango $E000-$FFFF, al rango $A000-$BFFF (rango del bloque alto del cartucho).
- Esperar unos cuantos nanosegundos, a que la PLA se entere de la "pirula" que acaba de ocurrir
- La PLA se entera de que hay un cartucho (de pronto GAME y EXROM a 0), y de que se esta accediendo a un rango del cartucho, asi que, por fin, establece el pin HIRAM, y el cartucho se entera de si KERNAL está activo, o si lo que hay es RAM.
- Si es RAM, (pin HIRAM a 1) pues no tiene nada que hacer: libera GAME y EXROM, y, si todo ha ocurrido lo suficientemente rápido, la RAM tiene aún tiempo de devolver el byte correspondiente.
Si el pin HIRAM estaba a cero, es que el KERNAL estaba activo. El siguiente paso, es pasar a modo ULTIMAX: se pone EXROM a 1, dejando GAME a 0, (con lo que vuelve a cambiar el mapa de memoria), y la PLA mapea el bloque $E000-$FFFF al cartucho, desactivando el KERNAL interno del C64,
por lo que el cartucho ya puede poner el byte que sea en el bus de datos.
- Se deja el dato activo los nanosegundos que dice el datasheet, e inmediatamente, se pasa de nuevo a modo "invisible": GAME y EXROM a 1.
O sea, que en medio ciclo de reloj del C64, hay que:
- Sobreescribir una línea del bus de direcciones. Esto ya es bastante "interesante". La CPU está intentando poner un "1" en esa línea, y el cartucho tiene que forzar a que sea un cero. Sí, esto es provocar un cortocircuito, durante unos cuantos nanosegundos.
- Cambiar 2 veces el mapa de memoria del C64, pasando de modo "no cartucho", a modo "cartucho 16KB", a modo "Ultimax".
Realmente, a mí me parece todo esto .. increíble como mínimo.
Post suuuper largo, pero una de las cosas para las que estoy metido en este proyecto, es para aprender sobre el C64, y ponérselo más fácil a cualquiera que también quiera aprender sobre estas historias. Hace 3 meses no sabía cómo funcionaba un cartucho de un C64, y es todo un mundo...
(Y no he puesto nada sobre REUS, freezers y otras bestias...)