Commodore BASIC
# Commodore BASIC

El Commodore BASIC, también conocido como PET BASIC o CBM-BASIC, es el dialecto del lenguaje de programación BASIC utilizado en la línea de computadoras domésticas de 8 bits de Commodore International, que se extiende desde el PET de 1977 hasta el C128 de 1985.

El núcleo se basa en Microsoft BASIC 6502 y, como tal, comparte muchas características con otros BASIC 6502 de la época, como Applesoft BASIC. Commodore obtuvo la licencia de BASIC de Microsoft en 1977 sobre la base de «un sólo pago, sin regalías» después de que Jack Tramiel rechazara la oferta de Bill Gates de una tarifa de US$3 ($13,42 en 2023) por unidad, diciendo: «Yo ya estoy casado», y no pagaría más de US$25 000 ($111 793 en 2023) por una licencia perpetua.

La versión original del PET era muy similar a la implementación original de Microsoft con pocas modificaciones. El BASIC 2.0 en el C64 también era similar y también se vio en algunos C128 y otros modelos. Los PET posteriores implementaban BASIC 4.0, similar al original pero agregando una serie de comandos para trabajar con disquete.

El BASIC 3.5 fue el primero en desviarse realmente, agregando una serie de comandos para soporte de gráficos y sonido en el C16 y Plus/4. El BASIC 7.0 se incluyó con el Commodore 128 e incluía comandos de programación estructurados del BASIC 3.5 del Plus/4, así como palabras clave diseñadas específicamente para aprovechar las nuevas capacidades de la máquina. Se agregaron un editor de sprites y un monitor de lenguaje de máquina. El último, BASIC 10.0, fue parte del Commodore 65 inédito.

## Historia

Commodore tomó el código fuente del BASIC y lo desarrolló internamente para todas sus otras computadoras domésticas de 8 bits. No fue hasta el Commodore 128 (con la V7.0) que se mostró un aviso de derechos de autor de Microsoft. Sin embargo, Microsoft había incorporado un huevo de pascua en la versión 2 del Commodore Basic que demostró su procedencia: escribiendo el (oscuro) comando WAIT 6502, 1 haría que Microsoft! apareciera en la pantalla. (El huevo de pascua estaba bien ofuscado: el mensaje no apareció en ningún desensamblado del intérprete).

El popular Commodore 64 implementaba el BASIC v2.0 en ROM a pesar de que la computadora se lanzó después de la serie PET/CBM que tenía la versión 4.0, porque la 64 estaba pensada como una computadora doméstica, mientras que la serie PET/CBM estaba dirigida a uso comercial y educativo donde se suponía que su lenguaje de programación incorporado se usaba más. Esto ahorró costos de fabricación, ya que el V2 encaja en ROM más pequeñas.

## Detalles técnicos

### Edición de programas

Una característica conveniente del intérprete BASIC residente en ROM y el KERNAL era el editor de pantalla completa. Aunque los teclados Commodore solo tienen dos teclas de cursor que alternan la dirección cuando presiona la tecla mayúsculas, el editor de pantalla permitía a los usuarios ingresar comandos directos o ingresar y editar líneas de programa desde cualquier lugar de la pantalla. Si una línea tenía el prefijo de un número de línea, se «tokenizaba» y se almacenaba en la memoria del programa. Las líneas que no comenzaban con un número se ejecutaban presionando la tecla RETURN cada vez que el cursor estaba en la línea. Esto marcó una mejora significativa en las interfaces de entrada de programas en comparación con otros BASIC de computadoras domésticas comunes en ese momento, que generalmente usaban un editor de línea, invocados por un comando EDIT separado, o un comando «copiar cursor», que truncaba la línea en la posición del cursor.

También tenía la capacidad de guardar archivos con nombre en cualquier dispositivo, incluido el casete, un dispositivo de almacenamiento popular en los días del PET y que permaneció en uso durante la vida útil de los Commodores de 8 bits como una forma económica de almacenamiento masivo. La mayoría de los sistemas solo admitían nombres de archivo en disquete, lo que hacía que guardar varios archivos en otros dispositivos fuera más difícil. El usuario de uno de estos otros sistemas tenía que observar la ubicación del archivo en el contador de la grabadora, pero esto era inexacto y propenso a errores. Con el PET (y BASIC 2.0), los archivos de los casetes se podían solicitar por nombre. El dispositivo buscaría el nombre del archivo leyendo datos secuencialmente, ignorando cualquier nombre de archivo que no coincida. El sistema de archivos también estaba respaldado por una poderosa estructura de registro que podía cargarse o guardarse en archivos. Los datos del casete Commodore se grabaron digitalmente, en lugar de métodos analógicos menos costosos (y menos confiables) utilizados por otros fabricantes. Por lo tanto, se requería el Datasette especializado en lugar de una grabadora de cinta estándar. Había adaptadores disponibles que usaban un conversor analógico a digital para permitir el uso de una grabadora estándar, pero estos costaban solo un poco menos que el Datasette.

El comando LOAD se puede usar con el parámetro opcional ,1 que cargará un programa en la dirección de memoria contenida en los dos primeros bytes del archivo (estos bytes se descartan y no se retienen en memoria). Si no se utiliza el parámetro ,1, el programa se cargará al inicio del área del programa BASIC, que difiere mucho entre máquinas. Algunas variantes de Commodore BASIC proporcionaron comandos BLOAD y BSAVE que funcionaron como sus contrapartes en Applesoft BASIC, cargando o guardando bitmap de ubicaciones de memoria especificadas.

El PET no admite programas reubicables y el comando LOAD siempre se cargará en los primeros dos bytes contenidos en el archivo del programa. Esto creó un problema al intentar cargar programas BASIC guardados en otras máquinas Commodore, ya que se cargarían en una dirección más alta que donde el BASIC de PET esperaba que estuviera el programa, había soluciones para «mover» los programas a la ubicación adecuada. Si un programa se guardaba en una máquina CBM-II, la única forma de cargarlo en un PET era modificando los primeros dos bytes con un editor de sector de disco ya que la serie CBM-II tenía su área de programa BASIC en $0, lo que daría como resultado que el PET intente cargar en la página cero y se bloquee.

Las palabras reservadas de Commodore BASIC se podían abreviar ingresando primero una pulsación de tecla sin cambio y luego una pulsación de tecla cambiada de la siguiente letra. Esto establece el bit alto, lo que hace que el intérprete deje de leer y analice la declaración de acuerdo con una tabla de búsqueda. Esto significaba que la declaración hasta donde se estableció el bit alto se aceptó como un sustituto para escribir el comando completo. Sin embargo, dado que todas las palabras clave de BASIC se almacenaron en la memoria como tokens de un solo byte, esto fue una conveniencia para la entrada de declaraciones en lugar de una optimización.

En el conjunto de caracteres predeterminado solo en mayúsculas, los caracteres desplazados aparecen como un símbolo gráfico; p.ej. el comando, GOTO, podría abreviarse G{Shift-O} (que se parecía a GΓ en pantalla). La mayoría de estos comandos tenían dos letras, pero en algunos casos eran más largos. En casos como este, había una ambigüedad, por lo que se necesitaban más letras del comando sin mayúsculas, como GO{Shift-S} (GO♥) que se requieren para GOSUB. Algunos comandos no tenían forma abreviada, ya sea por brevedad o ambigüedad con otros comandos. Por ejemplo, el comando, INPUT no tenía abreviatura porque su ortografía chocaba con la palabra clave separada INPUT#, que se encontraba más cerca del comienzo de la palabra clave en la tabla de correspondencia. El comando PRINT muy utilizado tenía un solo atajo ?, como era común en la mayoría de los dialectos de Microsoft BASIC. La abreviación de comandos con letras desplazadas es exclusiva de Commodore BASIC.

Este método de tokenización tenía una falla tal que si uno incluía un REM (declaración BASIC para agregar un comentario al código) seguido de un {Shift-L}, al intentar ver la lista de programas, el intérprete de BASIC abortaría inmediatamente la lista, mostraría un ?SYNTAX ERROR y volvería al mensaje READY.. Esta falla fue utilizada con algún efecto por los programadores que querían probar y proteger su trabajo, aunque era bastante fácil de eludir.

Al abreviar las palabras clave, era posible incluir más código en una sola línea de programa (lo que podía ocupar dos líneas de pantalla en pantallas de 40 columnas, es decir, C64 o PET, o cuatro líneas en la pantalla de 22 columnas de VIC-20). Esto permitió un ligero ahorro para almacenar líneas de programa, que de otra forma hubieran necesitado líneas adicionales. Todos los comandos BASIC se tokenizaron y ocuparon 1 byte (o dos, en el caso de varios comandos de BASIC 7 o BASIC 10) en la memoria sin importar de qué manera se ingresaron. Las líneas tan largas eran una molestia para editar. El comando LIST mostraba la palabra clave completa del comando, extendiendo la línea del programa más allá de las 2 o 4 líneas de pantalla que podían ingresarse en la memoria del programa.

### Rendimiento

Al igual que el intérprete de Microsoft BASIC, Commodore BASIC es más lento que el código de máquina nativo. Los resultados de las pruebas han demostrado que copiar 16 kilobytes de ROM a RAM toma menos de un segundo en código de máquina, en comparación con más de un minuto en BASIC. Para ejecutar más rápido que el intérprete, los programadores comenzaron a usar varias técnicas para acelerar la ejecución. Una era almacenar valores de coma flotante de uso frecuente en variables en lugar de usar valores literales, ya que interpretar un nombre de variable era más rápido que interpretar un número literal. Dado que la coma flotante es el tipo predeterminado para todos los comandos, es más rápido usar números de coma flotante como argumentos, en lugar de números enteros. Cuando la velocidad era importante, algunos programadores convertían secciones de programas BASIC a lenguaje ensamblador del 6502 o 6510 que se cargaba por separado desde un archivo o se metía en la memoria desde instrucciones DATA en el final del programa BASIC, y ejecutado desde BASIC usando el comando SYS, ya sea desde el modo directo o desde el propio programa. Cuando la velocidad de ejecución del lenguaje de máquina era demasiado grande, como para un juego o cuando se esperaba la entrada del usuario, los programadores podían sondear leyendo ubicaciones de memoria seleccionadas (como $C6 para el 64, o $D0 para el 128, que indica el tamaño de la cola del teclado) para retrasar o detener la ejecución.

Una característica única de Commodore BASIC es el uso de códigos de control para realizar tareas dentro de un programa, como borrar la pantalla o posicionar el cursor; estos se pueden invocar emitiendo un comando PRINT CHR$(X) donde X corresponde al código de control que se emitirá (por ejemplo, PRINT CHR$(147) es el código de control para limpiar la pantalla) o presionando la tecla en cuestión entre comillas, por lo tanto, al presionar ⇧ Mayús+CLR INICIO después de una comilla, se mostrará la representación visual del código de control BASIC (en este caso, un corazón invertido) que luego se actúa en la ejecución del programa (imprimir directamente los códigos de control usa menos memoria y se ejecuta más rápido que invocar una función CHR$). Esto es en comparación con otras implementaciones de BASIC que normalmente tienen comandos dedicados para limpiar la pantalla o mover el cursor. BASIC 3.5 y posteriores tienen comandos específicos para limpiar la pantalla y mover el cursor.

Las líneas de programa en Commodore BASIC no requieren espacios en ninguna parte (pero el comando LIST siempre mostrará uno entre el número de línea y la declaración), por ejemplo, 100 IFA=5THENPRINT "YES":GOTO160, y era común escribir programas sin espacios. Esta función se agregó para conservar la memoria, ya que el tokenizador nunca elimina ningún espacio insertado entre las palabras clave: la presencia de espacios da como resultado 0x20 bytes adicionales en el programa tokenizado que simplemente se omiten durante la ejecución. El tokenizador elimina los espacios entre el número de línea y la declaración del programa.

Las líneas de programa pueden tener un total de 80 caracteres en la mayoría de las máquinas, pero las máquinas con texto de 40 columnas harían que la línea pasara a la siguiente línea en la pantalla, y en el VIC-20, que tenía una pantalla de 22 columnas, las líneas de programa podían ocupar hasta cuatro. BASIC 7.0 en Commodore 128 aumentó el límite de una línea de programa a 160 caracteres (cuatro líneas de 40 columnas o dos líneas de 80 columnas). Al usar abreviaturas como ? en lugar de PRINT, es posible incluir aún más en una línea. BASIC 7.0 muestra un error de ?STRING TOO LONG (cadena demasiado larga) si el usuario ingresa una línea de programa de más de 160 caracteres de longitud. Las versiones anteriores no producían un error y simplemente mostraban el mensaje READY dos líneas hacia abajo si se excedía la longitud de la línea. El número de línea se cuenta en el número de caracteres en la línea del programa, por lo que un número de línea de cinco dígitos dará como resultado cuatro caracteres menos permitidos que un número de un dígito.

El orden de ejecución de las líneas de Commodore BASIC no estaba determinado por la numeración de líneas; en cambio, seguían el orden en que las líneas estaban vinculadas en la memoria. Las líneas de programa se almacenaban en la memoria como una lista enlazada simple con un puntero (que contenía la dirección del comienzo de la siguiente línea de programa), un número de línea y luego el código tokenizado para la línea. Mientras se ingresaba un programa, BASIC reordenaba constantemente las líneas del programa en la memoria para que los números de línea y los punteros estuvieran todos en orden ascendente. Sin embargo, después de ingresar un programa, alterar manualmente los números de línea y los punteros con los comandos POKE podría permitir una ejecución desordenada o incluso dar a cada línea el mismo número de línea. En los primeros días, cuando BASIC se usaba comercialmente, esta era una técnica de protección de software para desalentar la modificación casual del programa.

Los números de línea pueden variar de 0 a 65520 y toman cinco bytes en almacenarse independientemente de cuántos dígitos haya en el número de línea, aunque la ejecución es más rápida cuantos menos dígitos haya. Poner varias declaraciones en una línea usará menos memoria y se ejecutará más rápido.

GOTO y GOSUB buscarán hacia abajo desde la línea actual para encontrar un número de línea si se realiza un salto hacia adelante, pero en caso de un salto hacia atrás, la búsqueda comienza desde el inicio de la programa. Esto ralentizará los programas más grandes, por lo que es preferible colocar las subrutinas de uso común cerca del inicio.

Los nombres de variables solo son significativos para 2 caracteres; por lo tanto, los nombres de variable VARIABLE1, VARIABLE2 y VA se refieren todos a la misma variable.

Commodore BASIC también es compatible con los operadores bit a bit AND, OR y XOR; aunque esta característica era parte del código básico de Microsoft BASIC 6502, por lo general se omitió en otros implementaciones como Applesoft BASIC.

El formato numérico nativo de Commodore BASIC, como el de su padre MS BASIC, era en coma flotante. La mayoría de las implementaciones BASIC contemporáneas usaban un byte para el exponente y tres bytes para la mantisa. La precisión de un número de coma flotante que utiliza una mantisa de tres bytes es de solo unos 6,5 dígitos decimales, y el error de redondeo es común. Las implementaciones 6502 de Microsoft BASIC utilizaron aritmética de coma flotante de 40 bits, lo que significa que las variables requerían cinco bytes para almacenarse (cuatro bytes para la mantisa y un byte para el exponente) a diferencia de la coma flotante de 32 bits que se encuentra en BASIC-80.

Mientras que las implementaciones 8080/Z80 de Microsoft BASIC admitían variables enteras y de doble precisión, las implementaciones 6502 eran solo de coma flotante.

Aunque Commodore BASIC admite variables enteras con signo (indicadas con un signo de porcentaje) en el rango de -32768 a 32767, en la práctica solo se usan para variables de matriz y cumplen la función de conservar la memoria al limitar los elementos de la matriz a dos bytes cada uno (una matriz de 2000 elementos ocupará 10 000 bytes si se declara como una matriz de coma flotante, pero solo 4000 si se declara como una matriz de enteros). Denotar cualquier variable como un número entero simplemente hace que BASIC la convierta de nuevo a coma flotante, lo que ralentiza la ejecución del programa y desperdicia memoria, ya que cada signo de porcentaje requiere un byte adicional para almacenarse (ya que esto también se aplica a las matrices de números enteros, el programador debe evitar usarlas a menos que se usen matrices muy grandes que excederían la memoria disponible si se almacenaran como coma flotante). Además, no es posible hacer POKE o PEEK a ubicaciones de memoria por encima de 32767 con la dirección definida como un entero con signo.

Se puede usar un punto (.) en lugar del número 0 (por lo tanto, 10 A=. en lugar de 10 A=0 o 10 FOR A=.TO 100 en lugar de 10 FOR A=0 to 100), esto se ejecutará un poco más rápido.

Commodore agregó la declaración SYS, utilizada para iniciar programas en lenguaje de máquina, y no estaba en el código BASIC original de Microsoft, que presentaba solo la función USR para invocar rutinas de lenguaje de máquina. La declaración SYS carga automáticamente los registros de la CPU con los valores en $30C-$30F (C64, varía en otras máquinas); esto se puede usar para pasar datos a rutinas de lenguaje de máquina o como un medio para llamar a funciones del kernel desde BASIC (como ejemplo, POKE 780,147:SYS 65490 borra la pantalla).

Dado que las máquinas Commodore de 8 bits que no sean C128 no pueden iniciar automáticamente el software del disco, la técnica habitual es incluir un código auxiliar BASIC como 10 SYS 2048 para comenzar la ejecución del programa. Es posible iniciar automáticamente el software después de la carga y no requerir que el usuario escriba una declaración RUN, esto se hace con un fragmento de código que conecta el vector BASIC «ready» en $0302.

Al igual que con la mayoría de las otras versiones de Microsoft BASIC, si una matriz no se declara con una instrucción DIM, se establece automáticamente en diez elementos (en la práctica, 11, ya que los elementos de la matriz se cuentan desde 0). Las matrices más grandes deben declararse o BASIC mostrará un error cuando se ejecute el programa y una matriz no se puede volver a dimensionar en un programa a menos que todas las variables se borren mediante una declaración CLR. Las matrices numéricas se llenan automáticamente con ceros cuando se crean, puede haber un retraso momentáneo en la ejecución del programa si se dimensiona una matriz grande.

Las variables de cadena se representan etiquetando el nombre de la variable con un signo «$». Por lo tanto, las variables AA$, AA y AA% se entenderían como distintas. Las variables de matriz también se consideran distintas de las variables simples, por lo que A y A(1) no se refieren a la misma variable. El tamaño de una matriz de cadenas simplemente se refiere a cuántas cadenas se almacenan en la matriz, no al tamaño de cada elemento, que se asigna dinámicamente. A diferencia de otras implementaciones de Microsoft BASIC, Commodore BASIC no requiere que se reserve espacio de cadena al comienzo de un programa.

A diferencia de otras máquinas de 8 bits como Apple II, todas las máquinas de Commodore tienen un reloj incorporado que se inicializa en 0 al encenderse y se actualiza con cada marca del temporizador PIA/VIA/TED/CIA, por lo tanto, 60 veces por segundo. Se le asignan dos variables de sistema en BASIC, TI y TI$, que contienen la hora actual. TI es de solo lectura y no se puede modificar; si lo hace, aparecerá un mensaje de error de sintaxis. TI$ se puede usar para establecer la hora a través de una cadena de seis números (se produce un error al usar una cadena que no sea de seis números). El reloj no es un método de cronometraje muy confiable, ya que se detiene cada vez que se desactivan las interrupciones (realizadas por algunas rutinas del kernel) y acceder al puerto IEC (o puerto IEEE en el PET) retrasará la actualización del reloj unos pocos tics.

La función RND en Commodore BASIC puede usar el reloj para generar números aleatorios; esto se logra mediante RND(0), sin embargo, tiene un uso relativamente limitado ya que solo se devuelven números entre 0 y 255. De lo contrario, RND funciona igual que otras implementaciones de Microsoft BASIC en el sentido de que se utiliza una secuencia pseudoaleatoria a través de un valor semilla fijo de 5 bytes almacenado al encender en ubicaciones de memoria $8B-$8F en la C64 (la ubicación difiere en otras máquinas). RND con cualquier número superior a 0 generará un número aleatorio amalgamado del valor incluido con la función RND y el valor inicial, que se actualiza en 1 cada vez que se ejecuta una función RND. RND con un número negativo va a un punto en la secuencia del valor semilla actual especificado por el número.

Dado que la generación de números aleatorios verdaderos es imposible con la declaración RND, es más común en el C64 y C128 utilizar el canal de ruido blanco del chip SID para números aleatorios.

BASIC 2.0 sufría notoriamente de una recolección de cadenas basura extremadamente lenta. La recolección de basura se invoca automáticamente cada vez que se ejecuta una función FRE y si hay muchas variables de cadena y matrices que se han manipulado en el transcurso de un programa, borrarlas puede llevar más de una hora en las peores condiciones. Tampoco es posible cancelar la recolección de basura ya que BASIC no escanea la tecla RUN/STOP mientras realiza esta rutina. BASIC 4.0 introdujo un sistema mejorado de recolección de basura con punteros hacia atrás y todas las implementaciones posteriores de Commodore BASIC también lo tienen.

La función FRE en BASIC 2.0 sufría de otra falla técnica en el sentido de que no puede manejar números con signo superiores a 32768, por lo tanto, si la función se invoca en un C64 (38k de memoria BASIC), se mostrará una cantidad negativa de memoria BASIC libre (sumando 65535 al número informado obtendrá la cantidad correcta de memoria libre). El PET y el VIC-20 nunca tuvieron más de 32k de memoria total disponible para BASIC, por lo que esta limitación no se hizo evidente hasta que se desarrolló la C64. La función FRE en BASIC 3.5 y 7.0 corrigió este problema y FRE en BASIC 7.0 también se «dividió» en dos funciones, una para mostrar la memoria de texto de programa BASIC libre y la otra para mostrar memoria de variables libre.

## Alternativas

Se lanzaron muchas extensiones BASIC para Commodore 64, debido a las capacidades relativamente limitadas de su BASIC 2.0 nativo. Una de las extensiones más populares fue DOS Wedge, que se incluyó en el Commodore 1541 Test/Demo Disk. Esta extensión al BASIC de 1 KB agregó una serie de comandos relacionados con el disco, incluida la capacidad de leer un directorio de disco sin destruir el programa en la memoria. Sus funciones se incorporaron posteriormente en varias extensiones de terceros, como el popular cartucho Epyx Fast Load. Otras extensiones de BASIC agregaron palabras clave adicionales para facilitar la codificación de sprites, sonido y gráficos de alta resolución como el Simons' BASIC.

Aunque la falta de funciones de sonido o gráficos de BASIC 2.0 fue frustrante para muchos usuarios, algunos críticos argumentaron que, en última instancia, era beneficioso ya que obligaba al usuario a aprender lenguaje de máquina.

Las limitaciones de BASIC 2.0 en el C64 llevaron al uso del lenguaje de máquina incorporado en la ROM del BASIC. Para cargar un archivo en una ubicación de memoria designada, una llamada leería el nombre del archivo, la unidad y el número de dispositivo: SYS57812"filename",8; la ubicación se especificaría en los registros X e Y: POKE780,0:POKE781,0:POKE782,192; y la rutina de carga se llamaría con: SYS65493.

Una revista en disco para el C64, Loadstar, era un lugar de encuentro para programadores aficionados que compartían colecciones de proto-comandos para BASIC, llamados con el comando SYS dirección + desplazamiento.

Desde el punto de vista de la programación moderna, las versiones anteriores de Commodore BASIC presentaban una serie de artimañas de mala programación para el programador. Como la mayoría de estos problemas derivaban de Microsoft BASIC, prácticamente todos los BASIC de computadoras domésticas de la época sufrían deficiencias similares. El programador asignaba un número de línea a cada línea de un programa Microsoft BASIC. Era una práctica común incrementar los números en algún valor (5, 10 o 100) para facilitar la inserción de líneas durante la edición o depuración del programa, pero una mala planificación significaba que insertar grandes secciones en un programa a menudo requería reestructurar todo el código. Una técnica común era iniciar un programa en algún número de línea bajo con tabla de saltos ON...GOSUB, con el cuerpo del programa estructurado en secciones que comenzaban en un número de línea designado como 1000, 2000, etc. Si fuera necesario agregar una sección grande, simplemente se le podría asignar el siguiente número de línea principal disponible e insertarla en la tabla de salto.

Las versiones BASIC posteriores en Commodore y otras plataformas incluían un comando DELETE y RENUMBER, así como un comando de numeración de línea AUTO que seleccionaría e insertaría automáticamente números de línea de acuerdo con un incremento seleccionado. Además, todas las variables se tratan como variables globales. Los bucles claramente definidos son difíciles de crear, lo que a menudo hace que el programador confíe en el comando GOTO (esto se rectificó más tarde en BASIC 3.5 con la adición de DO, LOOP, WHILE, UNTIL y EXIT). Las variables de bandera a menudo debían crearse para realizar ciertas tareas. Los BASIC anteriores de Commodore también carecen de comandos de depuración, lo que significa que los errores y las variables no utilizadas son difíciles de encontrar. Las estructuras IF...THEN...ELSE, una parte estándar de Microsoft BASIC Z80, se agregaron a BASIC 3.5 después de no estar disponibles en versiones anteriores de Commodore BASIC.

## Usar como interfaz de usuario

Al igual que otras computadoras domésticas, las máquinas de Commodore se iniciaban directamente en el intérprete BASIC. Los comandos de programación y archivo de BASIC se pueden ingresar en modo directo para cargar y ejecutar software. Si la ejecución del programa se detuviera con la tecla RUN/STOP, los valores de las variables se conservarían en la RAM y se podían consultar con el comando PRINT para su depuración. El 128 incluso dedicó su segundo banco de 64k al almacenamiento de variables, lo que permitió que los valores persistieran hasta que se emitiera un comando NEW o RUN. Esto, junto con el editor de pantalla avanzado incluido con Commodore BASIC le dio al entorno de programación una sensación similar a REPL; los programadores podían insertar y editar líneas de programa en cualquier ubicación de la pantalla, creando el programa de forma interactiva. Esto contrasta con los sistemas operativos orientados a los negocios de la época como CP/M o MS-DOS, que normalmente se iniciaban en un interfaz de línea de comandos. Si se requería un lenguaje de programación en estas plataformas, se tenía que cargar por separado.

Si bien algunas versiones de Commodore BASIC incluían comandos DLOAD y DSAVE específicos del disco, la versión integrada en Commodore 64 carecía de estos, lo que requería que el usuario especificara el número de dispositivo de la unidad de disco (normalmente 8 o 9) en el comando estándar LOAD, que de lo contrario sería el casete. Otra omisión del BASIC 2.0 de la Commodore 64 fue un comando DIRECTORY para mostrar el contenido de un disco sin borrar la memoria principal. En la 64, la visualización de archivos en un disco se implementó como la carga de un «programa» que, cuando se listaba, mostraba el directorio como un pseudo programa BASIC, con el tamaño de bloque del archivo como número de línea. Esto tuvo el efecto de sobrescribir el programa cargado en la memoria. Los complementos como DOS Wedge superaron esto al mostrar la lista del directorio directamente en la memoria de la pantalla.

## Versiones y características

Una lista de versiones de CBM BASIC en orden cronológico, con características añadidas sucesivamente:

### Versiones publicadas

* V1.0: PET 2001 con teclado chiclet y Datasette (PET original)
   * matrices limitadas a 256 elementos
   * El comando PEEK está explícitamente deshabilitado en ubicaciones de ROM BASIC por encima de $C000
* V2.0 (primer lanzamiento): PET 2001 con teclado de viaje completo y ROM actualizada
   * agrega soporte IEEE-488
   * mejoró la recolección de basura
   * corregir error de matriz
   * Easter egg: al ingresar WAIT6502,[number] se muestra MICROSOFT! un número arbitrario de veces
* V4.0: serie PET/CBM 4000/8000 (y última versión del PET 2001)
   * operaciones de disco: DLOAD,DSAVE,COPY,SCRATCH, etc (15 en total)
   * variables del canal de error de disco: DS,DS$
   * Rendimiento de recolección de basura muy mejorado
* V2.0 (segunda versión, después de 4.0): VIC-20; C64
* V4+: serie CBM-II (también conocida como gama B, P)
   * manejo de memoria: BANK
   * más operaciones de disco: BLOAD, BSAVE, DCLEAR
   * visualización formateada: PRINT USING, PUDEF
   * error de captura: DISPOSE
   * bifurcación alternativa: ELSE
   * manejo dinámico de errores: TRAP, RESUME, ERR$
   * lectura flexible de DATA: RESTORE [linenumber]
   * función de búsqueda de cadenas: INSTR
* V3.5: C16/116, Plus/4
   * comandos de sonido y gráficos
   * entrada de joystick: JOY
   * conversión decimal ↔ hexadecimal: DEC,HEX$
   * bucle estructurado: DO, LOOP, WHILE, UNTIL, EXIT
   * asignación de tecla de función: KEY (también modo directo)
   * ingreso/edición de programas: AUTO, DELETE, RENUMBER
   * depuración (rastreo): TRON, TROFF
   * comando de entrada MLM: MONITOR
   * huevo de Pascua C(1)16, Plus/4: ingrese <código>SYS 52650</código>
* V7.0: C128
   * más comandos de sonido y gráficos, incluido el manejo de sprites
   * editor de sprites integrado: SPRDEF
   * bloques de sentencias múltiples para estructuras IF THEN ELSE: BEGIN,BEND
   * paddle, lápiz óptico: JARRO,PEN
   * Función o exclusiva: XOR
   * obtener la dirección de la variable: POINTER
   * ventanas en modo texto: WINDOW
   * retardo de tiempo controlado: SLEEP
   * gestión de memoria: SWAP, FETCH, STASH, FRE(1)
   * uso de la conmutación de bancos de memoria del 128 para almacenar el código del programa por separado de las variables. Los valores de las variables se conservarían en las ejecuciones del programa si el programa se iniciara con el comando GOTO.
   * más operaciones de disco: BOOT, DVERIFY
   * Ajuste de velocidad de CPU: FAST,SLOW (2 vs 1 MHz)
   * entrar en modo C64: GO64
   * sin documentar, funcionando: RREG (lee los registros de la CPU después de un SYS)
   * comandos no implementados: OFF,QUIT
   * Huevo de Pascua C128: ingrese SYS 32800,123,45,6

### Versiones inéditas

* V3.6: Commodore LCD (prototipo inédito). Casi idéntico a V7.0, con las siguientes diferencias:
   * VOLUMEN en lugar de VOL
   * EXIT en lugar de QUIT
   * Comandos FAST, SLOW no presentes
   * Comando adicional: POPUPS
* V10: Commodore 65 (prototipo inédito)
   * comandos de gráficos/video: PALETTE, GENLOCK
   * entrada de ratón: MOUSE, RMOUSE
   * utilidad de archivo de texto (SEQ): TYPE
   * edición de programas: FIND, CHANGE
   * gestión de memoria: DMA, FRE(2)
   * comandos no implementados: PAINT, LOCATE, SCALE, WIDTH, SET, VIEWPORT, PASTE, CUT

## Paquetes de extensión notables

* Super Expander (VIC-20; entregado en cartucho ROM) (Commodore)
* Super Expander 64 (C64; cartucho) (Commodore)
* Simons' Basic (C64; cartucho) (Commodore)
* Graphics BASIC (C64; disquete) (Hesware)
* BASIC 8 (C128; disquete y chip ROM interno opcional) (Walrusoft)
