PETSCII 80 Converter

Recientemente nos donaron en el museo una maravillosa CBM PET 8032

Ya contábamos con otra PET, el modelo 4032, que son muy similares, pero la principal diferencia es el display: como sugiere el nombre, la 8032 tiene un display de 80 columnas, mientras que la 4032 solo tiene 40.

Si bien para la 4032 hay una variedad interesante de software (incluso modernos, como Attack of Petscii Robots), siendo la 8032 un modelo más “profesional” no encontré demasiado software, por lo que decidí comenzar a desarrollar algo para mostrar a los visitantes en esta máquina.

El principal problema que tengo es mi total incapacidad artística (y menos con caracteres PETSCII), por lo que se me ocurrió que podria armar un slideshow/animacion con PETSCII art, para lo cual tendria que utilizar algunos de los tantos utilitarios que convierten imagenes en petscii.

El problema que encontré fue que todos estos utilitarios generan PETSCII para la C64 y en 40 columnas (por lo que no me servían para generar pantallas para la 8032) tras lo cual decidí implementar yo mismo un conversor de imagen B&W a PETSCII.

El conversor toma una imagen en PNG, en 1 bit de profundidad de color, a una resolución de 640×200, y genera un archivo con los códigos que se pueden importar en cualquier compilador de assembler (aca voy a poner un ejemplo en kickassembler, el que utilizo yo).

Para utilizar el conversor lo mejor es utilizar algun software de edición de imágenes (ejempo: GIMP), ajustarla en tamaño a 640×400, luego la pasamos a B&W con 1 bit de profundidad de color (para eso mejor aplicar un filtro threshold, para evitar tramas). Finalmente reescalamos todo a 640×200 (la mitad de altura) sin aplicar ningun tipo de suavizado (nada de bilinear ni esas cosas, smoothing none), y lo guardamos como PNG.
Esta imagen “preprocesada” es la que vamos a usar como entrada en nuestro programa. 

El programa está escrito en Python 3, por lo que es requisito que esté instalado en nuestro sistema. Para utilizarlo simplemente escribimos “python convert.py <imagen_de_entrada.png> <output.raw>”, lo que nos generará un archivo de 2000 bytes, que es lo que ocupa una pantalla en la PET 8032.

Ejemplo de uso:

Supongamos que tenemos una imagen como esta:

entonces la llevamos a 640x400px. 

La razón de utilizar primero una resolucion de 640×400 y luego escalar verticalmente a la mitad es porque la “resolución” de pantalla de la pet es en realidad 640×200, pero los pixeles son el doble de altos que ancho, y para trabajar la imagen en el GIMP de manera que se visualice correctamente es mejor hacer todo en 640×400, y al final escalar a 640×200.

Una vez que acomodamos en tamaño, el siguiente paso es convertir esta imagen en B&W con 1 bit de profundidad de color. Para ello lo mejor es utilizar primero el filtro Threshold (disponible en todos los programas de edición de imágenes), ajustamos el slider hasta lograr el mejor resultado, y luego convertimos esta imagen a monocromo 1 bit. Esto es necesario porque simplemente en la PET no tenemos ningun color, ni escala de grises.


Queda un último paso, que es reescalar a la mitad, para que el software pueda realizar la conversión correctamente.

Para ello vamos a las opciones de Image Resizing de nuestro software, y reescalamos a 640×200 (quitamos el bloqueo de aspect ratio), y desactivamos todo tipo de suavización (nada de bilinear, trilinear ni esas cosas).

Exportamos esta imagen como PNG, y este lo utilizaremos como archivo de entrada con el conversor.


¿Por qué no hago todos estos ajustes automaticamente? Al fin y al cabo, la libreria PIL (tratamiento de imágenes en Python) permite hacer todo esto.

La razón es muy simple: Si automatizo estos pasos no tengo control sobre tamaños, ni ajustes de threshold, ni sobre qué efectos aplicar (a veces conviene por ejemplo aplicar un posterizado a 3 colores, y sobre eso realizar la conversion con un tramado por position), por lo que decidí que el programa SOLO realice la conversion del bitmap a characters, y el procesado que lo realice el usuario de la forma y con las herramientas que le parezcan.

Y como lo importamos en nuestro .asm?

Como mencionamos anteriormente, con “python convert.py image.png petscii.raw” convertimos la imagen a petscii. Luego podemos importarla y utilizarla como nos parezca. A continuación un ejemplo ultra sencillo:

 * = $0400 "Basic Upstart"
 // Esto basicamente escribe en BASIC lo siguiente: SYS 1050
.byte $00, $0c, $04, $0a, $00, $9e, $20, $31, $30, $35, $30, $00, $00, $00

* = 1050
main:
	// SETEAMOS EL SET DE CARACTERES MAYÚSCULAS
    ldx #12
    stx 59468 

    rts

* = 32768 "SCREEN"
.import binary "petscii.raw"

lo compilamos con kickassembler, cargamos el PRG en el vice (con el ejecutable xpet.exe), y obtenemos nuestra pantalla en PETSCII


y eso es todo…
el código del conversor lo pueden obtener de github: https://github.com/moonorongo/petsciiator80

Hasta el próximo post!

BASIC – 8 – Animaciones (3)

Con todo lo aprendido en los post anteriores vamos a realizar una pequeña animación. Para ello definiremos 2 sprites, que serán los frames del famosisimo Space Invaders:

El programa que estoy utilizando aquí es C64 Studio, un IDE de programación que entre otras cosas trae un sencillo editor de sprites que me permite exportar los DATA a lineas de BASIC, y lo pueden descargar desde aquí: https://www.georg-rottensteiner.de/en/index.html

Luego cargaremos estos valores a partir de la memoria 12288, que corresponden a los punteros 192 y 193. Para hacer una animación solamente tenemos que implementar un loop FOR, y alternamos estos valores en cada iteración.
La parte interesante que la podemos ver a continuación:

100 for sx = 24 to 255
110 poke v,sx
120 poke 2040,192 + ((sx and 8) / 8)
130 next 

El loop se encuentra entre las lineas 100-130, en la linea 110 se va actualizando la posición y en la linea 120 se especifica que frame mostrar segun esa posición.
El truco aquí esta en “+ ((sx and 8) / 8)”: este código toma el valor 1 o 0 segun el estado del bit 3 en la variable sx.
De esta forma las primeras 8 posiciones tomaran el valor 0, lo que hará que el puntero quede seteado en la posición 192, en las siguientes 8 posiciones quedará en 1, por lo que el puntero sera 193, en las siguientes 8 volverá a 0 … y así indefinidamente.
Si quisiéramos que la animacion se reproduzca mas rápido podemos checkear el estado de los bits de menor peso y si queremos que se reproduzca mas lento chequeamos los bits de mayor peso.
Aqui podemos ver como se ve nuestro alien animado:

y el listado completo a continuación:

10 v=53248 
20 poke v+21,1
30 poke 2040,192
40 for t=12288 to 12414
50 read n
60 poke t,n
70 next
80 poke v+39,1
90 poke v+1,75

100 for sx = 24 to 255
110 poke v,sx
120 poke 2040,192 + ((sx and 8) / 8)
130 next 

150 for sx = 255 to 24 step -1
160 poke v,sx
170 poke 2040,192 + ((sx and 8) / 8)
180 next 

200 goto 100

1000 data 14,7,0,14,7,0,3,12
1010 data 0,3,12,0,15,255,0,15
1020 data 255,0,60,243,192,60,243,192
1030 data 255,255,240,255,255,240,207,255
1040 data 48,207,255,48,204,3,48,204
1050 data 3,48,7,158,0,7,158,0
1060 data 0,0,0,0,0,0,0,0
1070 data 0,0,0,0,0,0,0,1
1080 data 14,7,0,14,7,0,195,12
1090 data 48,195,12,48,207,255,48,207
1100 data 255,48,252,243,240,252,243,240
1110 data 255,255,240,255,255,240,63,255
1120 data 192,63,255,192,28,3,128,28
1130 data 3,128,48,0,192,48,0,192
1140 data 0,0,0,0,0,0,0,0
1150 data 0,0,0,0,0,0,0,1

Y esto es todo por hoy, nos vemos en la próxima entrega!

BASIC – 7 – Sprites (2)

En el post anterior vimos como activar un sprite, como seleccionar el area de memoria que dara la forma a nuestro sprite, y lo posicionamos en la pantalla.
Hoy vamos a darle la forma definitiva, para ello tenemos 2 vias:

  1. Usar un editor de sprites, que nos genere los numeros necesarios
  2. Hacerlo a mano

Hoy vamos a optar por la segunda opción, mas que nada para aprender como se hacía a la antigüa usanza, despues podremos utilizar multitud de programas que nos permiten dibujar comodamente y exportar los datos al formato que deseemos

Los sprites en la C64 poseen un tamaño de 24 x 21 pixels, lo que nos da 3 bytes (24px) por 21 = 63 bytes.
Para definir un sprite “a la antigüa” dibujaremos una cuadricula de 24×21, agrupando en columnas de 8 pixels. Luego pintaremos las casillas con los puntos que componen nuestro gráfico, para finalmente convertir cada grupo de 8 pixels en un byte.
Por ejemplo, aqui tenemos un circulo solido relleno:

Cada grupo de 8 bits los convertimos primero a binario, y luego a decimal (podemos utilizar la calculadora de windows, seteandola en modo programador), de forma que el primer byte es 00000000, que en decimal es “0”, el segundo 01111110 es “126” en decimal, y asi con el resto.
A continuación tenemos el programa completo, con los 63 bytes que definen nuestra “pelota”.

10 v=53248
20 pokev+21,1: rem activamos sprite numero 1
30 poke2040,192: rem direccion de inicio 12288
40 fort=12288to12350 : rem leemos los 63 valores
45 read n
50 poke t,n
60 next
70 pokev+39,1: rem elegimos color blanco
80 pokev,100: rem posicion horizontal 100
90 pokev+1,110: rem posicion vertical 110
100 data 0, 126, 0
110 data 3,255,192
120 data 7,255,224
130 data 31,255,248
140 data 31,255,248
150 data 63,255,252
160 data 127,255,254
170 data 127,255,254
180 data 255,255,255
190 data 255,255,255
210 data 255,255,255
220 data 255,255,255
230 data 255,255,255
240 data 127,255,254
250 data 127,255,254
260 data 63,255,252
270 data 31,255,248
280 data 31,255,248
290 data 7,255,224
300 data 3,255,192
310 data 0, 126, 0

Ademas de poder posicionar nuestro sprite en cualquier parte de la pantalla, tambien podemos elegirle un color, expandirlo al doble a lo ancho, o alto, o ambos.
Para darle un color utilizaremo el registro 39 (v + 39 seria) y un número entre 0 y 15 para especificar que color queremos asignarle

Para expandir a lo ancho tenemos el registro 29, y para expandir a lo alto el registro 23. Cada uno de estos registros son de 8 bits, y cada bit se corresponde con el sprite que queremos expandir, así que por ejemplo, si queremos expandir el sprite 1 a lo ancho deberiamos tipear POKE V+29,1
y si queremos expandir el sprite 8 a lo alto lo hacemos con POKE V+23,128
Aqui podemos ver como jugamos un poco con estos registros:
Y con esto tenemos suficiente por hoy. Nos vemos en el proximo capitulo!

BASIC – 6 – SPRITES (1)

Los sprites en la C64 son objetos que podemos definir como nosotros deseemos, y que se pueden posicionar en cualquier parte de la pantalla. Al ser manejados por hardware no tenemos que preocuparnos por preservar el fondo de pantalla, ni mover bytes, pintarlos ni nada que en otras computadoras es tarea corriente.
La C64 puede manejar hasta 8 sprites, y cada uno de ellos se les puede asignar un color independiente, expandirlos en el eje X o Y, posicionarlos en cualquier parte de la pantalla, y un monton de cosas mas.
Cada sprite tiene un tamaño de 24×21 pixels, y ocupa 63 bytes en memoria

En este pequeño ejemplo vamos a definir un sprite cuadrado (todo con el valor 255, que en binario es 11111111), y vamos a ver como lo podemos mover, expandir y cambiar el color.
Primero vamos a ingresar este programa en la c64, con el que vamos a poder ejemplificar varios conceptos 😀

10 v=53248 
20 poke v+21,1
30 poke 2040,16
40 for t=1024 to 1087
50 poke t,255
60 next
70 poke v,100
80 poke v+1,110

En la primera linea seteamos la variable v con el valor 53248. Este valor corresponde al primer registro de los 46 que posee el chip de video de la C64 (el VIC2). De esta manera solamente tenemos que recordar una posición de memoria, y ciertos registros claves.
El primer registro aparece en la linea 20, el número 21, y corresponde al numero de sprite activo, en este caso el número 1. Luego aparece una dirección de memoria (2040) con el que podemos especificar que segmento de la memoria del VIC2 queremos utilizar para definir la forma de nuestro sprite.

NOTA acerca del direccionamiento de memoria del VIC2:
Si bien el 6510 (el microprocesador de la C64) puede direccionar hasta 64kb de memoria, el VIC2 solo puede direccionar 16kb. Por razones que escapan a esta introducción, el VIC2 se puede configurar para que utilize cualquiera de los 4 bancos de 16Kb, y por defecto cuando encendemos la C64 esta configurado para trabajar en el banco 0 (el bloque de memoria que va de 0 a 16384)

En la dirección de memoria 2040, entonces, podemos especificar el lugar donde se almacenarán los valores que daran forma a nuestro Sprite, en segmentos de 64 bytes. Para nuestro ejemplo utilizamos el valor 16, que multiplicado por 64 nos da … 1024… mhmmm..
Eso lo vimos en un post anterior, en el que imprimíamos en pantalla utilizando POKEs directamente en la dirección de video del VIC2.
La idea de utilizar la memoria de video es mostrar como se va llenando la memoria con los valores que necesita el sprite (lineas 40 – 60), y como podemos modificarlos y ver como se reflejan esas modificaciones en la figura del sprite. Por supuesto que en un juego real no vamos a utilizar esa direccion, porque donde borramos la pantalla o actualizamos cualquier valor se nos rompe el sprite.
Finalmente en las lineas 70 y 80 posicionamos el sprite en pantalla.
Si ejecutamos el programa obtendremos el siguiente resultado (observen como se modifica el sprite cuando altero las 2 primeras lineas de texto en pantalla)

Observese tambien que se ve un puntito que representa el cursor.
En la siguiente entrega ya vamos a darle una forma mejor, y vamos a mostrar el uso de los diferentes registros.

BASIC – 5 – Leer el joystick para mover objetos

En el post anterior vimos como mover un caracter por la pantalla, pero habia algunas limitaciones, como por ejemplo que no podiamos realizar diagonales, y que cada vez que queríamos avanzar debíamos pulsar repetidamente las teclas.

Hoy vamos a hacer el mismo programa, pero controlando la pelota con el joystick conectado en el port 2, pero primero… un poco de teoria.

Para leer las posiciones del joystick tenemos las posiciones de memoria 56321 (port 1) y 56320 (port 2).
los bits 0,1,2,3 corresponden a las direcciones (arriba, abajo, izquierda, derecha) y el bit 4 corresponde al boton de disparo.
Estando el joystick en posicion central, sin pulsar disparo estas direcciones nos devuelven el valor 127, que corresponde a %01111111, y a medida que vamos moviendo el joystick y pulsando el disparo se ponen en 0 los bits correspondientes.
Podemos ver rapidamente como se comportan los valores con un sencillo programita de 3 lineas

20 j=peek(56320)
30 print j
40 goto 20

Copia este programa y cuando lo ejecutes comenzara a imprimir el valor 127. Conecta un joystick al port 2 y veras como varia este valor segun las direcciones que muevas.

Vamos ahora si con el programa de la bola modificado para joystick

10 x = 10: y = 10
20 poke 1024 + (40 * y)+ x, 81
30 j = not(peek(56320)) and 127
40 if j = 0 then 30
50 poke 1024 + (40 * y)+ x, 32
60 dx = -((j and 4) / 4) + ((j and 8) / 8)
70 dy = -(j and 1) + ((j and 2) / 2)
80 x = x + dx: y = y + dy
90 poke 1024 + (40 * y)+ x, 81
100 goto 30

Como es usual, primero definimos en la linea 10 la posicion inicial en pantalla, y a continuacion imprimimos la bola. A continuacion leemos el valor del port 2 y, para poder hacer unas operaciones despues, vamos a invertir los bits, y poner el bit 7 en 0 (con esto lo que logramos es que cuando pulsemos el bit se ponga en 1, en vez de 0)

Las otras lineas interesantes son la 60 / 70, que obtienen el valor dx / dy haciendo unos calculos. La ventaja de hacerlo de esta manera sobre el tradicional chequeo de IFs es que ocupa menos lugar (importantisimo) y que ya nos resuelve la deteccion de diagonales (con estas 2 lineas evitamos 8 lineas de IFs)

En la linea 80 actualizamos las posiciones, luego imprimimos la bola, y vuelta a chequear el valor del port 2.
A continuacion podemos ver la diferencia con el programa anterior

El proximo post vamos a comenzar a utilizar sprites. Hasta la próxima!

BASIC – 4 – Leer el teclado para mover cosas

El BASIC de la C64 nos provee 2 instrucciones para ingresar información desde el teclado:

  1. INPUT : Para casos en los que queremos ingresar un nombre o un valor numérico
  2. GET : para cuando necesitamos detectar solo la pulsación de una tecla

Para lo que queremos hacer ahora vamos a utilizar el comando GET. El modo de uso es muy simple, solo toma como parámetro la variable en la que queremos que coloque el valor de la tecla pulsada.
Con este pequeño ejemplo vemos como funciona:

10 get a$
20 print a$;
30 goto 10

Si ejecutamos aparentemente no realiza nada, pero si pulsamos una tecla aparecera su correspondiente letra en la pantalla. Lo que esta haciendo aqui es un loop infinito en el que lee el valor de la tecla pulsada, lo imprime, y vuelve a leer, asi indefinidamente.
Con todo esto podemos hacer nuestro programita en el que controlamos una bola

10 px% = 10: py% = 10
20 a$ = ""
30 get a$ : if a$="" then 100
40 poke 1024+(py%*40)+px%,32
50 if a$="d" then px%=px%+1
60 if a$="a" then px%=px%-1
70 if a$="s" then py%=py%+1
80 if a$="w" then py%=py%-1
90 poke 1024+(py%*40)+px%,81
100 goto 30

Nuevamente definimos nuestras variables de posición, luego leemos el valor de la tecla pulsada, y si no se detecto ninguna salteamos la parte de código que mueve nuestro personaje.
Esto tal vez no tenga demasiado sentido en este ejemplo, pero en juegos mas complejos esta bueno que si no se pulsa ninguna tecla se puedan hacer otras cosas (no tiene sentido volver a imprimir el personaje en la misma posición)

En las siguientes lineas borramos la bola de la posición anterior (el caracter 32 es el Espacio), comprobamos si se pulsó alguna de las teclas W, A, S, D, e imprimimos la bola en la posición actualizada.
NOTA: se podria optimizar mucho más este ejemplo, pero a efectos didácticos vamos a mantenerlo simple.

Y así es como queda:

Agregando una cola que vaya guardando las posiciones anteriores podemos implementar un juego tipo Nibbles, o cualquier cosa que necesitemos mover por la pantalla

BASIC – 3 – Imprimiendo En Pantalla (2)

Vimos en el post anterior que tenemos 2 formas de imprimir en pantalla: con el comando PRINT tradicional o directamente cargando valores en la memoria de video.

La memoria de video de la C64 se compone (simplificando mucho, para lo que queremos explicar) de una matriz de 40 columnas por 25 filas de caracteres, lo que nos da un total de 1000 caracteres. En cualquiera de estas posiciones podemos imprimir lo que deseemos, simplemente colocando el valor correcto.

La posición de memoria 1024 es el inicio de nuestra memoria de video. En ella se encuentra el caracter que corresponde a la esquina superior izquierda de la pantalla, y a medida que vamos incrementando esta posición los caracteres van llenando la pantalla.


Para muestra, vale este pequeño ejemplo:

10 for x = 0 to 1000
20 poke 1024 + x, 81
30 next

Aqui podemos ver como se va llenando la pantalla, de izquierda a derecha, las 1000 posiciones de la misma.


¿Y si queremos posicionar algo? Es muy sencillo, simplemente con esta formula:

m = 1024 + (40 * py) + px

Donde m es la posición de memoria, px es la columna y py es la fila donde queremos posicionar nuestro gráfico. Con toda esta información podemos escribir un pequeño programita que nos dibuja una pelota rebotando por la pantalla:

10 px% = 10: py% = 10: dx% = 1: dy% = 1
20 poke 1024+(py%*40)+px%,32
30 px% = px% + dx%
40 py% = py% + dy%
50 if px%=39 then dx% = -dx%
60 if px%=0 then dx% = -dx%
70 if py%=24 then dy% = -dy%
80 if py%=0 then dy% = -dy%
90 poke 1024+(py%*40)+px%,81
100 goto 20

px y py son la posición de la pelota; dx y dy su dirección.


Inmediatamente pintamos un espacio, porque si no lo hacemos la pelota nos dejará una estela de pelotas, luego incrementamos la posicion según la dirección en la que está yendo, hacemos las comprobaciones para que no salga de la pantalla, y finalmente imprimimos la pelota… y reinicia el ciclo.

Y el resultado es el siguiente… bueno, mas o menos, la captura de pantallas esta hecha a 15 cuadros (frames) por segundo, lo que hace que la pelota desaparezca un poco.

Partiendo de este código se puede realizar un clon de breakout o similar

En el próximo post vamos a ver como leer el teclado, ycontrolar con WASD nuestra bola

BASIC – 2 – Imprimiendo en pantalla (1)

Para imprimir letras o los simbolos gráficos predefinidos en nuestra C64 tenemos 2 formas de hacerlo:

  1. con el comando PRINT de toda la vida
  2. accediendo directamente a la memoria de video

El comando PRINT nos permite imprimir una cadena de texto que le pasaremos entre comillas dobles
Ej: si tipeamos PRINT “HOLA MUNDO” nos imprime HOLA MUNDO en la pantalla, en la posición del cursor.

Es muy práctico cuando tenemos que imprimir texto, pero se puede llegar a complicar si queremos posicionar algo en la pantalla, ya que el BASIC de la C64 no tiene un comando para posicionar el cursor en la pantalla rapidamente.

Podemos, sin embargo, usar la instruccion SPC(n), que nos genera n espacios. No es exactamente para posicionar, pero podemos utilizarla para este fin en algunos casos, como por ejemplo:

1 rem carretera endiablada
10 x% = 10
20 a% = rnd(0) * 3 - 1
30 x% = x% + a%
40 if (x% > 28) then x% = 28
50 if (x% < 0) then x% = 0
60 print spc(x%); "o      o"
70 goto 20

Este pequeño programita de 7 líneas nos genera una carretera con scroll, como podemos ver en el siguiente video:

El programa es muy simple:
  • Las líneas 10-20 definen posición del camino y dirección que tomará (el signo % al lado de las variables las define como “integer” (o “número entero”, sin decimal), tener en cuenta porque si no por defecto son “float” ( o “número de punto flotante”, es decir, con decimal), y todas las operaciones son más lentas)
  • En la línea 30 ajusta la posición del camino según la dirección al azar que tomó.
  • En las líneas 40 y 50 se realizan comprobaciones para que no se salga de la pantalla.
  • La línea 60 imprime el camino.
  • … y finalmente vuelve a repetir el ciclo desde la línea 20, saltando a este punto con GOTO.

En el próximo post veremos como imprimir accediendo directamente a la memoria de video

BASIC – 1 – Introducción

Hola, mi nombre es Mauro Cifuentes, y vamos a realizar una serie de posteos en los que voy a ir mostrando lo que podemos hacer en el BASIC 2.0 de C64.
Para quien no la haya utilizado nunca, tiene algunas peculiaridades propias de una época en la que no habia nada estandarizado, tanto en el lenguaje como en la forma en que se introducen los programas.

En este primer post, mi intención es explicar alguna de esas peculiaridades para que el novato no se pierda al intentar tipear su primer programa.

Formato de texto

Como es muy probable que quien desee comenzar a programar en BASIC no tenga una C64 original, sino que lo haga a traves de un emulador (que por otra parte tiene innumerables ventajas para desarrollar) decidí escribir todos los ejemplos en minusculas, asi directamente pueden copiarlos con Ctrl-C y pegarlos en el emulador con Alt-Insert. Así, si tenemos un listado como el siguiente:

10 print "bienvenidos al curso ";
20 goto 10

si lo copiamos con Ctrl-C y lo pegamos en el emulador aparecerá así:

Como podemos ver, todas las minusculas en la C64 aparecen como mayusculas, y si en los textos yo escribo con mayusculas, en la C64 aparecerán simbolos graficos.
Por ejemplo, si el listado anterior lo paso a mayusculas:

10 PRINT "BIENVENIDOS AL CURSO ";
20 GOTO 10

y lo copio y pego en el emulador, nos aparecerá esto, que obviamente va a tirar un error:

por eso mismo, TODOS los listados que aparezcan estaran en minusculas, para que puedan copiarlos y pegarlos facilmente.

“Peculiaridades”

Como mencioné antes, la C64 tiene algunas particularidades para ingresar texto. Por ejemplo, por defecto SIEMPRE el modo de escritura es de sobreescribir, por lo que si ponemos el cursor sobre una linea con código ya escrito lo que tipeemos a partir de alli va a sobreescribir lo que estaba.

Otra particularidad es la apertura / cierre de comillas dobles (en la C64 no existen las comillas simples, por lo que a partir de ahora me voy a referir simplemente como comillas).
Por ejemplo: nosotros podemos mover libremente el cursor por la pantalla con las teclas de cursor, tambien podemos borrar toda la pantalla con la combinacion de teclas Shift+Home, o incluso podemos cambiar el color del cursor con las teclas CTRL+<número>, del 1 al 8 podemos seleccionar con que color queremos escribir en la pantalla.
PEEERO, si por alguna razon tipeamos una comilla veremos que si pulsamos los cursores, o Shift+Home o queremos cambiar el color del cursor nos salen caracteres “raros”, invertidos.
Ejemplo a continuación

Esto nos sirve para poner dentro de una instruccion PRINT los desplazamientos de caracteres, o colores, o borrar la pantalla. Una instruccion muy comun en otras computadoras para borrar la pantalla es CLS, pero en nuestra C64 tenemos que tipear lo siguiente:

El corazon invertido es lo que aparece cuando pulsamos Shift-Home. De la misma manera podemos “programar” posicionamientos de texto y secuencias de colores, por ejemplo:

este simple comando borra la pantalla, mueve el cursor 4 posiciones abajo y 4 a la derecha, en cada letra cambia el color del cursor, y “TEC” lo escribe en texto invertido, para finalmente setear el cursor en blanco para mejor legibilidad

Pasa exactamente lo mismo cuando insertamos texto. Previamente dijimos que por defecto lo que tipeamos sobreescribe lo que esta bajo el cursor.
Si queremos INSERTAR texto (por ejemplo, queremos modificar algo del código) necesitaremos insertar caracteres tantos como necesitemos (no tenemos un modo insert como en cualquier editor moderno) y allí podemos escribir.
Ejemplo:

Recursos

Emulador VICE:
https://vice-emu.sourceforge.io/index.html#download
BASIC 2.0:
https://www.c64-wiki.com/wiki/BASIC
https://www.c64-wiki.com/wiki/C64-Commands
https://www.c64-wiki.com/wiki/BASIC#Overview_of_BASIC_Version_2.0_.28second_release.29_Commands