Idioma
Ver el código de Programar Cartuchos
{{toc numerate=1}}
===Introducción===
Aquí explicaremos de forma fácil cómo programar los cartuchos más comunes para nuestros Atari de 8 bits; partiremos de los más estándar a algunos un poco más complejos.
También es necesario saber ensamblador y conocer un poco del equipo a nivel de Hardware.
Cabe señalar que existieron cartuchos más pequeños de tamaño 2 Kb y 4 Kb en los primeros programas y juegos comerciales, pero nos enfocaremos en los más comunes.
===Herramientas ===
Como ensamblador usaremos ((https://github.com/tebe6502/Mad-Assembler/releases Mads)) por su actualización continua y por algunas macros propias que te ahorran líneas de código cuando necesitas instrucciones de ensamblador lda/sta; para editor, dejamos que los usuarios seleccionen el que les sea más cómodo, pero tenemos guías para ((/Guías/ConfiguracióndemadsconNotepadplusplus Notepad++)) y ((/Guías/Configuraciondemadsconvscode VS Code)).
También recomendamos leer ciertos libros como ((/Biblioteca/AtariRoots Atari Root)) y el ((/Biblioteca/MapeandoElAtari Mapeando el Atari)) versión actualizada del The Mapping ATARI.
===Cartucho de 8 Kb===
Partiremos con el más común de todos, el de 8 kb; esto quiere decir que la información se podrá acceder en el rango de las posiciones de memoria de $A000 al $BFFF, o sea, vamos a tener 8.192 bytes para nuestros programas. **Es importante destacar que esto es de lectura**; no podemos cambiar algún valor en este rango en tiempo de ejecución.
Ahora un ejemplo simple y explicaremos más abajo ciertos detalles importantes a tener en cuenta.
%%(hl php numbers=2)
opt f+h-
org $A000
dlist
.by $70,$70,$70,$70,$70,$70,$70,$47
.wo screen
.by $7,$70,$6,$41
screen
.sb " cartridge "
.sb " 8 KB "
.sb " WWW.ATARIWARE.CL "*
start
mwa #dlist $230
jmp *
end
rts
org $BFFA
.wo start
.by 0,4
.wo end
%%
Para generar el archivo ROM, se hace con la siguiente instrucción desde la consola, que es lo más básico :
%%
mads cart_8kb.asm -o:cart_8kb.rom
%%
((https://www.atariware.cl/archivos/prgcart/cart_8kb.webp align=center))
Ahora explicaremos las líneas importantes:
* **Línea 1 :** Le indicamos al ensamblador Mads que rellene con $FF los bytes restantes para completar 8.192 bytes y además que elimine la cabecera que se agrega automáticamente para los ejecutables (XEX).
* **Línea 3 :** La dirección definida por el sistema operativo de donde comienza un cartucho de 8 KB.
* **Líneas 5 a la 8 :** Definición de una lista de despliegue (diseño de pantalla).
* **Líneas 10 a la 13 :** Mensaje que se colocará en el diseño de pantalla definido anteriormente.
* **Líneas 15 a la 17 :** Programa principal y donde se activa el diseño de pantalla definido anteriormente con un ciclo infinito para que se quede en el programa.
* **Líneas 19 a la 20 :** Fin del programa del cartucho y que vuelva al sistema operativo del ATARI.
* **Líneas 22 a la 25 :** Esto es la cabecera del cartucho; siempre debe estar en la posición $BFFA. Tiene dos bytes que indican dónde inicia el programa del cartucho; siguen los bytes 0, 4, que es un cartucho estándar, y los últimos dos bytes, que es donde termina el programa del cartucho.
%%(info type="note")
El ensamblador usado tiene algunas macros propias para ahorrar tiempo y que sea menos largo el código ensamblador, por ejemplo, la instrucción **mwa** usada en la línea 16.
Al generar el archivo, el ensamblador lo convierte a las típicas instrucciones:
lda #$00
sta $230
lda #$A0
sta $231
%%
Ahora, lo último a tener en cuenta: como anteriormente se dijo, no vamos a tener acceso a modificar ningún valor desde el rango $A000 hasta $BFFF, ya que esto es ROM. Entonces, si necesitamos cambiar un diseño de pantalla o datos de los bytes, deberá usar la RAM; se recomienda usar el rango $1000 al $9FFF cuando sea para un cartucho de 8 kb y su Atari sea 64 kb de RAM.
Un ejemplo: si necesito definir una pantalla y cambiar una línea de tamaño gráfico, lo normal sería que el diseño esté en la ROM y copiemos los bytes a una nueva posición de memoria en la RAM, hagamos la modificación y, por último, actualicemos la pantalla usando la nueva dirección.
¿Cómo sería en ensamblador aplicando lo descrito anteriormente?
%%(hl php numbers=2)
SDLSTL = $230
CONSOL = $D01F
opt f+h-
org $A000
dlist
.by $70,$70,$70,$70,$70,$70,$70,$47
.wo screen
.by $7,$70,$6,$41
screen
.sb " cartridge "
.sb " 8 KB "
.sb " WWW.ATARIWARE.CL "*
start
ldx #0
copy_dlist
lda dlist,x
sta $1000,x
inx
cpx #$E
bne copy_dlist
mwa #$1000 SDLSTL
key
lda CONSOL
cmp #6
beq key_start
cmp #5
beq key_select
jmp key
key_start
lda #7
sta $100C
jmp key
key_select
lda #6
sta $100C
jmp key
end
rts
org $BFFA
.wo start
.by 0,4
.wo end
%%
Explicaremos lo que agregamos para cambiar una línea de la lista de despliegue :
* **Líneas 1 y 2 :** Etiquetas definidas con un valor del Hardware de Atari correspondiente a la lista de despliegue y a las teclas de consola.
* **Líneas 19 a la 25 :** Copiamos nuestra lista de despliegue desde la ROM a la RAM, ubicándola en la posición de $1000.
* **Línea 26 :** Le decimos al sistema operativo que aplique la lista de despliegue que está en la RAM.
* **Líneas 28 a la 34 :** Preguntamos al sistema operativo si se presiona una de las teclas **START** o **SELECT**.
* **Líneas 35 a la 38 :** Si es la tecla **START**, entonces cambiamos en la RAM la posición de memoria $100C con el valor de $7, para que tenga letras más grandes en la línea del texto www.atariware.cl.
* **Líneas 39 a la 42 :** Si es la tecla **SELECT**, entonces cambiamos en la RAM la posición de memoria $100C con el valor de $6, para que vuelva a tener letras pequeñas en la línea del texto www.atariware.cl.
Con esto concluimos con el tema importante de cómo colocar algunas cosas en la memoria RAM para poder manipularlas después en nuestro programa que se está ejecutando como un cartucho.
===Cartucho de 16 Kb===
Continuamos con el segundo tipo de cartucho de 16kb, esto quiere decir que la información se podrá acceder en el rango de las posiciones de memoria de $8000 al $BFFF, o sea, vamos a tener 16.384 bytes para nuestros programas.
Ahora vamos con el ejemplo; algunas cosas no se explicarán, ya que se aplica lo mismo que se usa en el cartucho de 8 kb.
%%(hl php numbers=2)
SDLSTL = $230
opt f+h-
org $8000
dlist
.by $70,$70,$70,$70,$70,$70,$70,$47
.wo screen
.by $7,$70,$6,$41
screen
.sb " cartridge "
.sb " 16 KB "
.sb " WWW.ATARIWARE.CL "*
start
mwa #dlist SDLSTL
jmp *
end
rts
org $BFFA
.wo start
.by 0,4
.wo end
%%
((https://www.atariware.cl/archivos/prgcart/cart_16kb.webp align=center))
Esta vez no hay mucho que explicar, ya que todo es igual que el cartucho anterior, solo que ahora la posición inicial cambió a $8000, que es la línea 5.
Solo mencionaremos que estos dos tipos de cartuchos de 8 Kb y 16 Kb son los que maneja el hardware de Atari. Ahora te preguntarás qué pasa con los 32 Kb, 64 Kb, etc. En resumen, debes respetar el mismo formato de 8 kb o 16 kb, solo que usarán bancos de memoria que se irán cambiando para extraer la información y colocarla en la RAM.
===Cartucho XEGS de 32 Kb===
Este sería el tercer tipo más famoso y último que hizo Atari para su familia XL/XE. Como adelantamos, posee bancos de memoria que debes ir cambiando para ir leyendo su contenido. Explicaremos la más pequeña, que es de 32 Kb. Esta posee 4 bancos de memoria de 8 kb, o sea, 8.192 bytes por banco, pero uno de sus bancos es fijo, el cual inicia el cartucho.
* El banco de inicio sería el que está en el rango de memoria de $A000 al $BFFF y este no cambiará nunca, ya que es fijo.
* Los siguientes bancos usarán el rango de memoria de $8000 a $9FFF y se irán cambiando cada vez que nosotros queramos usando un número 0, 1, 2 y escribiéndolo en la dirección de memoria **$D500**.
((https://www.atariware.cl/archivos/prgcart/cart_xegs_bank.webp align=center))
La imagen es una ilustración de cómo es la estructura de este formato de cartucho. También se puede aplicar a sus versiones de más memoria de 64 Kb a 1MB; la única diferencia es que aumentan los bancos de memoria disponibles.
Después de la explicación de la estructura, partiremos con el primer ejemplo, el cual está enfocado solo en aprender cómo desde el banco principal hacemos el cambio de los otros bancos en el rango $A000 al $BFFF. Para ello, en cada banco colocaremos un mensaje para saber qué banco se leyó y mostrarlo en pantalla.
%%(hl php numbers=2)
FLPTR = $FC
CDTMF4 = $22C
COLOR2 = $2C6
CONSOL = $D01F
CPUTREC = $9
ICCOM = $342
ICBAL = $344
ICBAH = $345
ICBLL = $348
ICBLH = $349
CIOV = $E456
SETVBV = $E45C
opt h-
org $8000
dta c'Leyendo banco 0',$FD,$9B
:8175 .byte $FF
org $8000
dta c'Leyendo banco 1',$FD,$9B
:8175 .byte $FF
org $8000
dta c'Leyendo banco 2',$FD,$9B
:8175 .byte $FF
opt f+
org $A000
start_cart
lda #0
sta FLPTR
sta FLPTR+1
sta COLOR2
jsr print
lda #1
sta FLPTR+1
read_consol
lda CONSOL
cmp #6
bne no_consol
lda FLPTR
cmp #3
bne next_bank
lda #0
sta FLPTR
next_bank
inc FLPTR
sta $D500
jsr print
lda $800E
rol
sta COLOR2
no_consol
jsr wait
jmp read_consol
wait
ldx #0
ldy #5
lda #$FF
sta CDTMF4
lda #4
jsr SETVBV
loop
lda CDTMF4
bne loop
rts
print
ldx #0
mva #CPUTREC ICCOM,x
lda FLPTR+1
cmp #0
bne print_cart
mwa #text ICBAL,x
jmp print_exit
print_cart
mwa #$8000 ICBAL,x
print_exit
mwa #$A0 ICBLL,x
jsr CIOV
rts
text
dta c'presiona ',' START '*,' para ir leyendo los bancos de memoria del cartucho'
dta $7F,$7F,$7F,$7F,c'XEGS 32 KB',$7F,$7F,$7F,$7F
dta c' www.atariware.cl',$1D,$9B
end_cart
rts
org $BFFA
.word start_cart
.by $0,$4
.word end_cart
%%
((https://www.atariware.cl/archivos/prgcart/cart_xegs_32kb.webp align=center))
Ahora lo explicamos:
* **Línea 1 :** Posición de memoria de dos bytes; usamos los bytes por separado: el primero **FLPTR** para movernos de banco y **FLPTR+1** para controlar el mensaje que imprimiremos por pantalla.
* **Líneas 6 al 13 :** Posiciones que necesitas para poder usar el SIO para imprimir un mensaje.
* **Líneas 16 al 29 :** Aquí tenemos los bancos con un mensaje y rellenamos con $FF hasta cumplir con los 8.192 bytes por banco.
* **Líneas 34 al 41 :** Seteamos en cero las posiciones de **FLPTR** y mandamos a imprimir el primer mensaje; después cambiamos el valor a **FLPTR+1** para que muestre los mensajes de los bancos de memoria.
* **Líneas 42 al 50 :** Leemos las teclas de consola y preguntamos si es **START** para cambiar el valor consecutivo de **FLPTR**; también se validó que esté en el rango correspondiente.
* **Líneas 51 al 57 :** Aumentamos **FLPTR** y se lo pasamos a **$D500** para decirle que cambiamos al siguiente banco, mandamos a imprimir en pantalla el banco y, por último, cambiamos el color de fondo.
* **Líneas 58 al 60 :** Llamamos a la rutina de pausa.
* **Líneas 62 al 72 :** Rutina de pausa usando el sistema operativo para que, al presionar la tecla START, espere un momento entre mensaje.
* **Líneas 74 al 87 ** Rutina para imprimir un mensaje en la pantalla mediante el sistema operativo usando la unidad por defecto E:; mediante **FLPTR+1** discriminamos cuál mensaje va a colocar en pantalla.
Como segundo ejercicio, explicaremos cómo pasar un archivo binario de un juego a nuestro cartucho de 32 KB. Esto tiene unas limitantes por el tipo de cartucho que estamos usando; la más importante es que el juego debe estar entre las zonas de memoria $1000 A $7FFF; es porque el cartucho desde $8000 al $BFFF está activo como ROM.
Tomaremos un clásico juego llamado GORF y lo analizaremos; si es candidato, para ello usaremos el mismo emulador Altirra para activar la consola y arrastrar el juego gorf.xex al emulador.
((https://www.atariware.cl/archivos/prgcart/altirraconsole.webp align=center))
Si ves la consola, te mostrará los segmentos de memoria que usa al cargar este juego; por lo que se ve, es un segmento largo y continuo de memoria, $2000 al $48E3; entonces usaremos como un banco y un cuarto. También nos indica dónde se inicia el juego con el segmento $02E2 y $02E3, el cual tiene dos bytes, que sería $48D3, que es lo que nos importa.
Ahora viene el proceso de cómo sacar el segmento principal del juego que nos interesa, que sería el del $2000 al $48E3. Usamos la herramienta ((https://sourceforge.net/projects/dis6502 DIS6502)), ya sea su versión antigua o la más nueva; en ambos es lo mismo.
((https://www.atariware.cl/archivos/prgcart/dis6502.webp align=center))
Seleccionamos el segmento y vamos a guardar sin cabecera; con esto dejamos el segmento limpio sin la ((/Guías/ExtensiónXEX cabecera de los archivos .xex)). Con este paso tenemos el segmento total.
Usaremos otra herramienta llamada ((https://mh-nexus.de/en/hxd HxD)) que es un editor hexadecimal que nos ayudará a cortar una parte de 8 Kb y otra más pequeña de 2275 bytes. Una vez listos y guardados los archivos, dejaré un ((https://www.atariware.cl/archivos/prgcart/gorf.zip zip)) con los archivos, el ejecutable, segmento total, segmento parte 1 y, por último, segmento parte 2. Ahora pasaremos al ejemplo.
%%(hl php numbers=2)
FLPTR = $FC
org $80
mem_orig .ds 2
mem_dest .ds 2
opt h-
org $8000
ins 'gorf_part1.bin'
org $8000
ins 'gorf_part2.bin'
:5916 .byte $FF
org $8000
:8192 .byte $FF
opt f+
org $A000
start_cart
lda #0
sta $D500
mwa #$8000 mem_orig
mwa #$2000 mem_dest
lda #32
sta FLPTR
jsr copy8kb
lda #1
sta $D500
mwa #$8000 mem_orig
mwa #$4000 mem_dest
lda #9
sta FLPTR
jsr copy8kb
jmp $48D3
copy8kb
lda FLPTR
tax
ldy #0
copy_loop
lda (mem_orig),y
sta (mem_dest),y
iny
bne copy_loop
inc mem_orig+1
inc mem_dest+1
dex
bne copy_loop
rts
end_cart
rts
org $BFFA
.word start_cart
.by $0,$4
.word end_cart
%%
((https://www.atariware.cl/archivos/prgcart/gorf.webp align=center))
Ahora lo explicamos:
* **Líneas 3 al 5 :** Reservamos 2 bytes para la posición de origen de lectura de la memoria ROM y 2 bytes para la posición de destino en la memoria RAM.
* **Líneas 3 al 5 :** Incluimos la primera parte del juego, que debe ser de 8 Kb.
* **Líneas 11 al 13 :** Incluimos la segunda parte del juego y rellenamos con $FF lo restante para armar los 8 Kb.
* **Líneas 15 al 16 :** Debes llenar este banco con $FF para completar un tercer banco obligatorio para armar un cartucho de 32 Kb.
* **Líneas 22 al 28 :** Seleccionamos el banco 0 y seteamos las variables con los valores $8000, que es la memoria de origen ROM, y $2000 para la memoria de destino en RAM. También tenemos FLPTR con 32 para copiar todo $8000 a $9FFF y, por último, llamamos a la rutina de copia.
* **Líneas 30 al 36 :** Seleccionamos el banco 1 y seteamos las variables con los valores $8000, que es la memoria de origen ROM, y $4000 para la memoria de destino en RAM. También tenemos FLPTR con 9 para copiar un poco de bytes y, por último, llamamos a la rutina de copia.
* **Línea 38 :** Saltamos al inicio del juego, que anteriormente nos dijo el emulador Altirra.
* **Líneas 40 al 53 :** Rutina de copia de bytes, con la variable FLPTR; le damos el largo a copiar; siempre será múltiplo de 255 para copiar bloques largos.
===Conclusiones===
Como se vio, hemos mostrado cómo programar los diferentes cartuchos que ATARI vendía para su línea de 8 bits; siempre el movimiento de memoria entre el cartucho ROM y la RAM puede ser 8 Kb o 16 Kb, ya que el hardware fue diseñado así. Otra cosa, existe un cartucho conmutado XEGS, pero no estoy seguro si fue algo ideado por ATARI o idea de un tercero; por el momento no se explicará por ese motivo.
Bueno, se pueden hacer cosas entretenidas hoy en día. Si te estás preguntando por la parte electrónica, hay varios diseños para estos cartuchos en ((https://www.pcbway.com/project/ PCBWay)) en la sección proyectos que puedes mandar hacer y armar tu propio cartucho real.
----
{{navigation main="/Biblioteca" title=1}}