Está en la página 1de 126

25/9/2020 Mapping The C64

********* ¡

Bienvenido al Proyecto 64!

El objetivo del Proyecto 64 es preservar los documentos relacionados con Commodore 64


en formato de texto electrónico que de otra manera podrían dejar de existir con el
rápido avance de la tecnología informática y el interés decreciente en
las computadoras de 8 bits por parte de la población en general.

Se hicieron grandes esfuerzos para preservar el contenido del


documento original . Sin embargo, ciertas partes, como diagramas,
listas de programas e índices, pueden haber sido modificadas o sacrificadas debido
a las limitaciones del texto simple. Es posible que se hayan
eliminado los diagramas donde ASCII-art no era factible. Es posible que en las listas de programas
falten códigos de visualización donde las sustituciones no fueron posibles. Mesas
de contenidos e índices pueden haber cambiado de
referencias de números de página a referencias de números de sección. Acepte nuestras disculpas
por estas limitaciones, alteraciones y posibles omisiones.

Los nombres de los documentos están limitados a la convención de archivos 8.3 de DOS. Los
primeros caracteres del nombre del archivo son una abreviatura del
nombre del documento original . El número de versión del etext sigue a continuación. Después de
eso, puede aparecer una carta para indicar la fuente particular del
documento. Finalmente, el documento recibe una extensión .TXT.

El (los) autor (es) del documento original y los miembros del Proyecto 64
no hacen declaraciones sobre la exactitud o idoneidad de este material.
para cualquier propósito. Este etext se proporciona "tal cual". Consulte la
garantía del documento original, si corresponde, que puede estar incluido en este texto
electrónico. No se le otorga ninguna otra garantía, expresa o implícita, en cuanto al
etext o cualquier medio en el que pueda estar. Ni el (los) autor (es) ni los
miembros del Proyecto 64 asumirán responsabilidad por daños ya sea por
el uso directo o indirecto de este etext o por la distribución
o modificación de este etext. Por lo tanto, si lee este documento o
utiliza la información que contiene, lo hace bajo su propio riesgo.

*********

The Project 64 etext del ~ Mapping The Commodore 64 book ~, escrito


por David Holz <david_holz@hotmail.com>, formateado en 71 columnas y
algo corregido por Cris Berneburg <pcgeek@compuserve.com>.

MAPC6410.TXT, mayo de 1998, etext # 352 #

Nota del mecanógrafo cansado:

¡WHEW! Este es MUCHO texto. Y, sí, toda esta maldita


cosa de 11,000 líneas fue completamente escrita a mano. En cuanto al contenido, traté de obtener
todo exactamente palabra por palabra. Sin embargo, es probable que haya muchos errores tipográficos al
acecho en estas páginas. Por lo tanto, doy permiso para que cualquiera pueda editar
y volver a publicar este archivo sin tener que ponerse en contacto conmigo. También hice algunos
cambios menores, que incluyen eliminar los números de página y la
delimitación, llenar hasta 79 columnas de ancho, enumerar
texto con formato normal en tablas con formato algo y corregir
algunos errores tipográficos y errores en el texto original.

¡El libro lleva el nombre de Sheldon Leemon y fue publicado por Compute!
Publicaciones, (c) 1984. Nuevamente (como debería
leerse en el encabezado del Proyecto 64 ), esta copia es solo para referencia y para preservar su
contenido de la pérdida eterna. ¡Sin daños monetarios o de otro tipo a
Compute! Las publicaciones o Sheldon Leemon se entienden por la creación y
transferencia de este libro electrónico, y
por la presente se reconoce la propiedad intelectual del contenido de este texto por parte de las partes mencionadas.
¡No se obtendrá ningún beneficio de la transferencia de esta copia electrónica! No
asumo ninguna responsabilidad por nada de lo que alguien haga con el texto de
este documento, al igual que el autor y editor original.

Sin más preámbulos, ¡aquí está una de las mejores referencias de C64!
¡Disfrutar!

White Flame (también conocido como David Holz)


http://www.geocities.com/ResearchTriangle/Lab/1767

*********

MAPEANDO EL Commodore 64

::::::::::::
:: Contenido ::
::::::::::::

Prólogo

Agradecimientos

Introducción

Capítulo 1. Página 0

Capítulo 2. Página 1

Capítulo 3. Páginas 2 y 3
Almacenamiento de trabajo básico y básico

Capítulo 4.
Pantalla de 1K a 40K , memoria, Sprite Punteros y
texto de programa BÁSICO

www.unusedino.de/ec64/technical/project64/mapping_c64.html 1/126
25/9/2020 Mapping The C64

Capítulo 5. ROM BÁSICA 8K y RAM libre 4K

Capítulo 6. VIC-II, SID, dispositivos de E / S, RAM de color


y ROM de caracteres

Capítulo 7. ROM Kernal del sistema operativo 8K

Apéndice A. Una guía para principiantes para


escribir programas

Apéndice B. Cómo escribir programas

Apéndice C. Tabla de ubicación de pantalla

Apéndice D. Tabla de memoria de colores de pantalla

Apéndice E. Códigos de colores de pantalla

Apéndice F. Códigos ASCII


[*** OMITTED ***]
[ampliamente disponible en otros lugares; no es adecuado para formato de texto]

Apéndice G. Códigos de pantalla


[*** OMITIDO ***]
[ampliamente disponible en otros lugares; no apto para formato de texto]

Apéndice H. Commodore 64 codifica

Index (By Memory Location)

::::::::::::
::Foreword::
::::::::::::

This is a memory map of the Commodore 64 personal computer. But it's


much more than that. It's a reference book which every programmer who
uses the 64 will find invaluable. What is a memory map? It's a list
of the memory locations in a computer. But Mapping the Commodore 64
is a memory amp that goes much further. It explains the purpose of
each location and shows you how to change the contents of many of
them. You can make the computer do what you want it to. If you're a
BASIC programmer, you'll find easy-to-understand explanations of how
to use the advanced features of the Commodore 64, and how to include
estas funciones en sus propios programas. Si ya está utilizando el
lenguaje de máquina para escribir sus propios programas, utilizará esta guía una y otra vez.
una vez más, refiriéndose a ubicaciones y rutinas de memoria específicas.
Tendrá la guía más completa disponible para la memoria del Commodore 64
.

¡Como con todos los COMPUTE! libros, las explicaciones son claras y fáciles de
entender. Tanto los programadores principiantes como los avanzados encontrarán
Mapping the Commodore 64 como un recurso valioso.

::::::::::::::::::::
:: Agradecimientos ::
:::::::::::::::::::

Me gustaría agradecer Russ Davies, autor de Mapping the VIC, por su


generosidad al compartir los resultados de su investigación. Sin su ayuda,
y la de Dan Heeb, autor de The Commodore 64 y VIC Tool Kit,
este libro habría sido mucho menos completo.

De todas las fuentes de información publicadas sobre el 64, he encontrado que


la Guía de referencia del programador de Commodore 64 es la más valiosa
para obtener información técnica. Que Commodore haya realizado un
trabajo de referencia tan completo tan rápido después de la introducción de la
máquina es mucho para ellos. Debido a las similitudes entre
las computadoras Commodore 64 y anteriores, también he confiado en gran medida en los
ooks que se ocupan del PET / CBM. De particular interés son la
programación de PET / CBM de Raeto West, que debería estar subtitulada
"Todo lo que siempre quiso saber sobre las computadoras Commodore", y
la Guía de computadoras personales PET / CBM, tercera edición, Osborne /
McGraw-Hill. Estas importantes obras de referencia contienen más información
de beneficio real para el propietario del 64 que la mayoría de los libros que tratan
específicamente del 64.

Finalmente, me gustaría agradecer a mi esposa Lenore. Aunque su


contribución a este libro no fue de naturaleza técnica, fue tan
importante como cualquier otro.

:::::::::::::::
:: Introducción ::
::::::::::::::::

Para muchos usuarios de computadoras, el concepto de un mapa de memoria puede ser un


poco familiar. En pocas palabras, es una guía del
hardware y software internos de su computadora . Un mapa de memoria puede ayudarlo a usar las
instrucciones PEEK y POKE para extender sus poderes de programación BÁSICOS.
Si planea hacer programación en lenguaje de máquina, es necesario que
pueda orientarse en el sistema.

Muchos propietarios de computadoras piensan en un programa como algo que compran en una
tienda y lo introducen en la computadora para que les permita jugar,
procesar textos o llevar registros financieros. Pero este tipo de
www.unusedino.de/ec64/technical/project64/mapping_c64.html 2/126
25/9/2020 Mapping The C64
software de aplicaciones no es el único.

Es importante recordar que una computadora no puede hacer nada sin


algún tipo de programa. Cuando la computadora muestra el mensaje READY, o
el cursor parpadea, o muestra las letras que escribe, solo puede
hacerlo ejecutando un programa. En los ejemplos que se muestran arriba, es el
programa de control maestro, el sistema operativo (SO), que se está
ejecutando.

Cuando le da a la computadora un comando como LOAD, el


programa de interpretación BÁSICO traduce la solicitud similar al inglés al
idioma de los números que la computadora entiende. Los
programas de interpretación del sistema operativo y BASIC están contenidos en la
memoria de sólo lectura (ROM) permanente y están disponibles tan pronto como encienda la unidad.
Sin ellos, su computadora sería un pisapapeles bastante caro.

Este software permanente coexiste dentro de su computadora con el


programa de aplicaciones que carga. Dado que el software del sistema
realiza muchas de las mismas funciones que el programa de aplicaciones (como
como leer información del teclado y mostrarla en la
pantalla), a menudo es posible que el programa de aplicaciones haga uso
de ciertas partes del sistema operativo. Esto no solo facilita la
tarea del programador, sino que en algunos casos le permite
hacer cosas que de otro modo no serían posibles.

El Commodore 64 también tiene chips de soporte de hardware que permiten la


visualización de gráficos, la síntesis de sonido y las comunicaciones con
dispositivos externos . Dado que estos chips se tratan como memoria, ocupan
espacio en nuestro mapa. El control sobre estos chips, y las
funciones de gráficos, sonido y E / S que hacen posibles, solo se puede lograr mediante
manipulación de las direcciones de memoria que corresponden a estos
dispositivos. Por lo tanto, es necesaria una guía de estas direcciones
para aprovechar el poder de los gráficos, la música y las comunicaciones
que ofrecen.

El propósito de este libro es describir las ubicaciones de memoria utilizadas por


el sistema y mostrar, siempre que sea posible, cómo utilizarlas en
sus propios programas. El libro debería aclarar parte del misterio que
rodea al funcionamiento de su computadora.

Cómo utilizar este libro

Commodore 64 y comunicarse con 64K o 65536 (64 * 1024) bytes de


memoria. Cada uno de estos bytes de memoria puede almacenar un número del 0 al
255. La computadora puede leer (y a veces escribir) información de cualquier
de estas 65536 ubicaciones utilizando su dirección, un número de 0 a
65535.

Bits y Bytes

Cada byte se compone de ocho dígitos binarios llamados bits. Estos bits
son la unidad de información más pequeña de la computadora. Pueden contener
solo el número uno o el número cero, pero cuando se combinan, se pueden
usar para formar cualquier número necesario. Para ver cómo es posible, veamos
un solo bit.

Un solo bit solo puede ser un uno o un cero. Pero si se


combinan dos bits, el número aumenta.

00,01,10,11

Eso hace cuatro combinaciones posibles. Y si se agrega un tercer bit:

000,001,010,011,100,101,110,111

Cuando se juntan ocho bits, el número de combinaciones aumenta


a 256. Estos ocho bits se denominan byte y se pueden utilizar para
representar los números del 0 al 255.

Este sistema de numeración se conoce como binario (o base dos). Funciona de manera
muy similar al sistema decimal (base diez). En el
sistema de numeración de base diez , el dígito más a la derecha se conoce como el lugar de uno y contiene un
número del 0 al 9. El siguiente lugar a la izquierda se conoce como el
lugar de diez , y también contiene un número del 0 al 9, que representa el
número de veces que se ha utilizado el lugar de la unidad para contar (el número
de decenas).

En el sistema binario, hay un lugar para uno, luego un lugar para dos, un
lugar para cuatro, etc. Los bits se cuentan de derecha a izquierda, comenzando
con Bit 0. Estos son los valores de cada bit:

Bit 0 = 1
Bit 1 = 2
Bit 2 = 4
Bit 3 = 8
Bit 4 = 16
Bit 5 = 32
Bit 6 = 64
Bit 7 = 128

Si se suman todos los bits juntos (128 + 64 + 32 + 16 + 4 + 2 + 1), suman


255, que es el valor máximo de un byte. ¿Qué pasa si necesita
contar más de 255? Utilice dos bytes.

Al utilizar un segundo byte para contar el número de 255,


son posibles 65536 combinaciones (256 * 256). Este es el mismo número que los
bytes de memoria en el Commodore 64. Por lo tanto, cualquier byte puede ser
direccionado por un número usando un máximo de dos bytes.
www.unusedino.de/ec64/technical/project64/mapping_c64.html 3/126
25/9/2020 Mapping The C64

Cuando se habla de unidades de memoria grandes y uniformes, el segundo byte, el


número de 256, a menudo se utiliza solo. Estas unidades se conocen como páginas.
La página 0 comienza en la ubicación cero (0 * 256), la página 1 comienza en la ubicación 256
(1 * 256),

etc.Es posible que vea thn términos de byte bajo, orden de byte alto o LSB (
Byte menos significativo), MSB (Más Byte significativo), mencionado más adelante
en este libro. Eso se refiere a la forma en que el Commodore 64
generalmente maneja una dirección de dos bytes. El byte de la dirección que
representa el número de 256 (MSB) generalmente se almacena más alto en la
memoria que la parte que almacena el valor sobrante de 0 a 255
(LSB). Por lo tanto, para encontrar la dirección, debe agregar el LSB a
256 * MSB.

Hexadecimal

Otro sistema de numeración que se utiliza al hablar de computadoras es


el sistema hexadecimal (base 16). Cada dígito hexadecimal puede contar un
número del 0 al 15. Dado que el dígito numérico más alto es el 9, se
debe usar el alfabeto: A = 10, B = 11, y así sucesivamente hasta F = 15. Con solo
dos dígitos, son posibles 256 combinaciones (16 * 16). Eso significa que
cada byte puede representarse con solo dos dígitos hexadecimales, cada uno de los
cuales representa cuatro bits de memoria. Estas unidades de cuatro bits son
más pequeñas que un byte, por lo que se conocen como nybbles.

Dado que los programadores a menudo encuentran que los números hexadecimales son más fáciles de
usar que los números binarios o decimales, muchos números en este libro son
dado en formato decimal y hexadecimal. Se ha
colocado un signo de dólar ($) delante de cada número hexadecimal.

AND, OR, and EOR

Certain functions on the 64 (particularly those using the sound and


graphics chips) are controlled by a single bit. You will often see
references to setting Bit 6 to a value of one, or setting Bit 3 to a
value of zero. This can be done by adding or subtracting the bit
value for that particular bit from the value of the whole byte.

Adding or subtracting the bit value will work only if you know the
status of that bit already. If Bit 4 is off, and you add 16 (the bit
value of Bit 4) to the byte, it will turn Bit 4 on. But if it were on
already, adding 16 would turn Bit 4 off, and another bit on.

This is where logical (sometimes called Boolean) functions come in


práctico. Hay dos funciones, OR y AND, disponibles en BASIC, y una
tercera, EOR, se puede utilizar en la programación en lenguaje de máquina para la
manipulación de bits .

Y generalmente se usa para poner a cero (o enmascarar) bits no deseados. Cuando usted Y
un número con otro, aparecerá un 1 en el número resultante, solo
los bits idénticos en los números con Y se establecieron en 1. Por ejemplo,
si quisiera convertir el Bit 4 en el número 154, podría Y
con 239 (que es la combinación de bits máxima menos el valor de bit a
enmascarar; 255-16):

10011010 = 154
Y 11101111 = 239
--------
= 10001010 = 138

Al usar la función AND, nada se dañaría si intentáramos


apagar un bit que no estaba encendido. Siempre puede apagar un poco usando la
fórmula BYTEVALUE AND (255-BITVALUE). Recuerde, debe haber un 1 en
el mismo bit de ambos números para que el mismo bit en el resultado
tenga un 1.

La función opuesta, activando un bit, es realizada por la


instrucción OR . La función OR pone un 1 en el bit del
número resultante si había un 1 en el mismo bit en cualquiera de los dos números.
Por ejemplo, para volver a activar el Bit 4 en el número 138,
usaríamos la
instrucción 138 O 16 (el valor de bit para el bit que queremos activar):
10001010 = 138
O 00010000 = 16
--------
= 10011010 = 154

Nuevamente, no se produciría ningún daño si el bit ya estuviera activado . Un bit


siempre se puede activar con la fórmula BYTEVALUE O BITVALUE.

La tercera operación, EOR, solo se puede realizar en lenguaje máquina. Se


utiliza para invertir el valor de un bit. Si el bit del segundo número
tiene un 1, invertirá el valor del bit correspondiente en el
primer número. Por lo tanto, para cambiar todos los bits, puede EOR un
número por 255:

10011010 = 154
EOR 11111111 = 255
--------
= 01100101 = 101

Observe que esto produce el complemento del número original (256


menos el número). Siempre que desee cambiar un bit de 0 a 1, o de 1
a 0, puede EOR con el valor de ese bit.

El formato de las entradas

www.unusedino.de/ec64/technical/project64/mapping_c64.html 4/126
25/9/2020 Mapping The C64
Las entradas de este libro están organizadas en el nivel más general por
bloques grandes (las 256 ubicaciones de la página 0, por ejemplo, o las 8192
ubicaciones de la ROM BÁSICA). Al comienzo de estos bloques,
a menudo encontrará una explicación que le dará una idea de cómo se relacionan las
referencias en esa sección. Por lo general, esta descripción general
facilitará la comprensión de las explicaciones más detalladas de las
ubicaciones individuales en ese bloque.

Dentro de estos bloques más grandes, a veces verá algunas ubicaciones


agrupados bajo el título Rango de ubicación. Esta agrupación se realiza cuando
las ubicaciones están tan interrelacionadas que no tendría sentido tratar
de explicar una sin explicarlas todas.

Finalmente vienen las entradas para ubicaciones individuales. Estos dan la


dirección, primero en decimal, luego en hexadecimal y, a veces, una etiqueta.
Esta etiqueta es simplemente un dispositivo mnemónico, utilizado en la
programación en lenguaje de máquina , para facilitar la referencia a una ubicación de memoria en particular.
Aunque Commodore no ha publicado el código fuente para su
sistema operativo o BASIC, ha publicado algunas de estas etiquetas en
la Guía de referencia del programador de Commodore 64.

Otras etiquetas utilizadas aquí se toman de la memoria PET de Jim Butterfield


mapas, que han gozado de una amplia circulación entre los usuarios de Commodore.
Su uso aquí debería ayudar a 64 propietarios a adaptar la información sobre el PET
a sus propias máquinas.

La etiqueta mnemotécnica de una entrada va seguida de una descripción


de una línea de la ubicación. A menudo, aparecerá una explicación más detallada debajo de
eso, que va desde un par de oraciones hasta varias páginas.
Ocasionalmente, estas explicaciones acompañarán muestras de programas.

A veces, las descripciones de una sola línea identificarán una ubicación como una
bandera, un vector o un puntero. Una bandera es solo un número que el
programa usa para almacenar el resultado de una operación anterior. Un puntero
de vector suele ser una ubicación de dos bytes que contiene una
habla a. Generalmente, el término puntero se usa cuando la dirección apunta
al inicio de algunos datos, y vector se usa cuando la dirección apunta
al inicio de un programa en lenguaje de máquina. Sin embargo, a veces estos
términos se usarán indistintamente, con el significado claro del
contexto.

::::::::::::
:: Capítulo 1 ::
:: ::
:: Página 0 ::
::::::::::::

Ubicaciones de memoria 0-255 ($ 0- $ FF) tienen un significado especial en la


programación del lenguaje de máquina 6502 (el microprocesador 6510 del Commodore
64 comparte el mismo conjunto de instrucciones que el 6502). Dado que estas
direcciones pueden expresarse con un solo byte, las instrucciones que
Los datos de acceso almacenados en estas ubicaciones son más cortos y se ejecutan más
rápidamente que las instrucciones que operan en direcciones en una
memoria superior , lo que requiere dos bytes.

Debido a este tiempo de ejecución relativamente rápido, la mayoría del software 6502
hace un uso intensivo de ubicaciones de página cero. El 64 no es una excepción y
utiliza esta área para muchas variables y punteros importantes del sistema.

Además, las ubicaciones 0 y 1 tienen funciones especiales de entrada / salida en


el 6510. En el caso del 64, este puerto de E / S en el chip se utiliza para
seleccionar las posibles combinaciones de ROM, como veremos a continuación, y para
E / S del casete de control.

Rango de ubicación: 0-143 ($ 0- $ 8F)


Almacenamiento de trabajo BÁSICO

Esta parte de la página cero es utilizada únicamente por BASIC. Por tanto, un programa
escrito íntegramente en lenguaje máquina que no interactúe con BASIC
puede utilizar libremente esta área.

0 $ 0 D6510
6510 Registro de dirección de DATOS de E / S en chip

Bit 0: Dirección de E / S del bit 0 en el puerto en la siguiente dirección. Predeterminado = 1 (salida)


Bit 1: Dirección de E / S del Bit 1 en el puerto en la siguiente dirección. Predeterminado = 1 (salida)
Bit 2: Dirección de E / S del Bit 2 en el puerto en la siguiente dirección. Predeterminado = 1 (salida)
Bit 3: Dirección de E / S del Bit 3 en el puerto en la siguiente dirección. Predeterminado = 1 (salida)
Bit 4: Dirección de E / S del Bit 4 en el puerto en la siguiente dirección. Predeterminado = 0 (entrada)
Bit 5: Dirección de E / S del Bit 5 en el puerto en la siguiente dirección. Predeterminado = 1 (salida)
Bit 6: Dirección de E / S del Bit 6 en el puerto en la siguiente dirección. No utilizado.
Bit 7: Dirección de E / S del Bit 7 en el puerto en la siguiente dirección. No utilizado.

Esta ubicación es la primera de una serie de registros de hardware que


analizaremos. Aunque se pueden escribir y / o leer como RAM,
están conectados a dispositivos de hardware y su contenido afecta el
funcionamiento de los dispositivos.

Cada bit de este registro de dirección de datos determina si los


dispositivos periféricos pueden escribir en el
contenido del bit correspondiente en el puerto de E / S interno (consulte la ubicación 1). Si el bit se
establece en 0, indica la dirección del flujo de datos como Entrada, lo que
significa que el bit correspondiente del puerto de E / S se verá afectado por
déficits periféricos. Si el bit se establece en 1, indica Salida. En
el 64, solo los Bits 0-5 son significativos. En el encendido, este registro se
establece en 239 ($ EF), lo que indica que todos los bits, excepto el bit 4
(que detecta el interruptor de casete), están configurados para Salida.
www.unusedino.de/ec64/technical/project64/mapping_c64.html 5/126
25/9/2020 Mapping The C64

1 $ 1 R6510

Bit 0: Señal LORAM. Selecciona ROM o RAM en 40960 ($ A000). 1 = BÁSICO, 0 = RAM
Bit 1: Señal HIRAM. Selecciona ROM o RAM en 57344 ($ E000). 1 = Kernal, 0 = RAM
Bit 2: Señal CHAREN. Selecciona ROM de caracteres o dispositivos de E / S. 1 = E / S, 0 = ROM
Bit 3: Línea de salida de datos del casete.
Bit 4: Sentido del interruptor de casete. Lee 0 si se presiona un botón, 1 si no.
Bit 5: Control del interruptor del motor del casete. Un 1 enciende el motor, 0 lo apaga.
Bits 6-7: No conectado - no hay función definida actualmente.

La función principal de este registro es determinar qué bloques de


RAM y ROM abordará el microprocesador 6510. El Commodore 64
viene con 64K RAM, aunque normalmente no usa toda esa
RAM a la vez. Además, tiene una ROM de intérprete BÁSICA 8K, una
ROM Kernal del sistema operativo 8K , una ROM generadora de caracteres 4K, un
Dispositivo de interfaz de sonido (SID), un Controlador de interfaz de video 6566 (VIC-II)
y dos chips adaptadores de interfaz compleja 6526 .

Para abordar todos estos a la vez, se necesitarían 88 K, 24 K más allá del


límite de direccionamiento del microprocesador 6510. Para asignar
espacio de direcciones, el puerto de E / S se utiliza para afectar las líneas de direccionamiento,
y así determinar qué segmentos de RAM y ROM se direccionarán en
cualquier momento.

Bit 0. Este bit controla la señal LORAM. Un 0 en esta posición de bit


cambia la ROM BÁSICA y la reemplaza con RAM en las direcciones
40960-49151 ($ A000- $ BFFF). El valor predeterminado de este bit es 1.

Bit 1. El bit 1 controla la señal HIRAM. Un 0 en esta posición de bit


desconecta la ROM Kernal y la reemplaza con RAM en 57344-65535
($ E000- $ FFFF). Como el intérprete BASIC usa el Kernal, también se
cambia y se reemplaza por RAM. El valor predeterminado de este bit es 1.

El sistema permite utilizar una amplia gama de combinaciones de RAM y ROM


. Por supuesto, el programador BÁSICO tendrá poca necesidad, en
el curso normal de los eventos, para cambiar la ROM BÁSICA y el
Kernal. Para hacerlo, simplemente colgaría el sistema. Pero una forma de hacer
uso de esta función es mover el contenido de la ROM a las
direcciones de RAM correspondientes. De esa manera, puede modificar y
personalizar fácilmente el intérprete BASIC y las rutinas Kernal del sistema operativo, que
normalmente se fijan en la ROM. Por ejemplo, para mover BASIC a RAM, simplemente
escriba:

FOR I = 40960 TO 49151: POKE I, PEEK (I): NEXT

Aunque parece que tal programa no haría nada, de


hecho copia bytes de ROM a RAM. Esto se debe a que los datos que se
escriben en una ubicación ROM se almacenan en la RAM que reside en el
misma direccion. Entonces, mientras está PEEKing ROM, está POKEING RAM. Para
cambiar a su copia RAM de BASIC, escriba:

POKE 1, PEEK (1) Y 254.

Ahora está listo para realizar modificaciones. Los ejemplos de


modificaciones simples incluyen cambiar el texto que imprime el intérprete,
como el mensaje READY, el mensaje de encendido o la tabla de palabras clave.

Un ejemplo de esto último sería POKE 41122,69. Esto cambia la


palabra clave FOR a FER, de modo que BASIC respondería normalmente a un
bucle FER-NEXT , pero no reconocería FOR como sintácticamente correcto.

En el lado más práctico, puede cambiar el mensaje que


emite INPUT por dos puntos, en lugar de un signo de interrogación:

POKE 43846,58

No está limitado solo a cambios cosméticos de texto. Jim Butterfield


ha dado un ejemplo en COMPUTE! revista de cambiar el intérprete
para que asigne una cadena nula el valor ASCII 0. En la
versión ROM , el comando PRINT ASC ("") devolverá?
ERROR CANTIDAD ILEGAL . Esto es un inconveniente al INPUTAR una cadena, porque si el
usuario presiona RETORNO e intenta verificar el valor ASCII de la cadena
que ha ingresado, obtendrá este error. Al ingresar POKE
46991,5, esto se cambia para que PRINT ASC ("") ahora responda con un
cero.

Para el programador de lenguaje de máquina más serio, es bastante factible


agregar nuevos comandos o modificar los existentes desviando los vectores
que se discuten en la sección que cubre la ROM del intérprete BÁSICA.
Para ver un buen ejemplo de esta técnica, consulte el artículo "Gráficos de alta resolución
simplificados" de Paul Schatz en el primer libro de Commodore 64
Sound and Graphics de COMPUTE! El ejemplo del programa inserta nuevos
comandos gráficos en una versión RAM de BASIC. Cuando desee volver a
la ROM BÁSICA, ingrese POKE 1, PEEK (1) O 1.

Para aplicaciones de lenguaje de máquina, sería posible reemplazar los


programas ROM con un sistema operativo completamente diferente, o una
aplicación que tenga su propio edición de pantalla y funciones de E / S
incluidas. Tal aplicación primero tendría que cargarse desde el disco
en RAM. Se podría cargar un idioma que no sea BASIC, y luego
simplemente cambiar la ROM BASIC, mientras se sigue usando el sistema operativo Kernal.

O una aplicación de hoja de cálculo que contuviera sus propias rutinas de E / S podría
cambiar todas las ROM y tener el uso de toda la RAM que no es
realmente necesaria para el programa en sí, para los datos. Debe
recordarse, sin embargo, que antes de apagar el Kernal, es
necesario deshabilitar las interrupciones, ya que los vectores para estas interrupciones
www.unusedino.de/ec64/technical/project64/mapping_c64.html 6/126
25/9/2020 Mapping The C64
están contenidos en el Kernal.

Bit 2. Este bit controla la señal CHAREN. Un 0 en esta posición


activa la ROM del generador de caracteres, de modo que el
6510 pueda leerla en las direcciones 53248-57343 ($ D000- $ DFFF). Normalmente, este bit es
establecido en 1, de modo que mientras el chip VIC-II tiene acceso a la
ROM del generador de caracteres para crear la visualización de la pantalla, el usuario
no puede PEEK en ella. Dado que esta ROM se conmuta al sistema en
la misma ubicación que los dispositivos de E / S (chip SID, chip VIC-II y 6526
CIA), se pueden producir E / S cuando se conecta esta ROM.

La capacidad de conmutar la ROM del generador de caracteres es muy útil para


el programador que desea expirar con caracteres definidos por el usuario.
Los gráficos de caracteres modificados son una de las
herramientas gráficas más poderosas disponibles, pero a menudo el usuario no querrá redefinir un conjunto de
caracteres completo a la vez. Al leer la ROM de caracteres y
duplicando su contenido en RAM, el usuario puede reemplazar solo unos pocos
caracteres en el conjunto. El método para leer esta ROM en RAM desde
BASIC es el siguiente:

10 POKE 56333,127: POKE1, PEEK (1) Y 251: PARA I = 0 A 2048


20 POKE BASE + I, PEEK (53248 + I): SIGUIENTE: POKE 1, PEEK (1) OR 4: POKE 56333,129

El primer POKE es necesario para apagar la interrupción del temporizador del sistema.
Dado que los dispositivos de E / S se direccionan en el mismo espacio que la
ROM de caracteres , al cambiar esa ROM se cambian todas las E / S, por lo que es necesario
desactivar cualquier interrupción que utilice estos dispositivos.

El segundo POKE es el que cambia en la ROM de caracteres. El


ciclo del programa luego lee esta memoria ROM en la RAM, comenzando con el
dirección BASE. Tenga en cuenta que esta dirección debe comenzar en un
límite uniforme de 2K (una dirección uniformemente divisible por 2048) dentro del bloque de
memoria que actualmente son direcciones del chip VIC-II (para
obtener más información sobre dónde colocar los conjuntos de caracteres definidos por el usuario y cómo
úselos, consulte la sección sobre el chip VIC-II, en la ubicación 53272
($ D018), la sección sobre la ROM de caracteres en 49152 ($ C000) y la
sección sobre almacenamiento de memoria VIC-II en 56576 ($ DD00)) . Después de leer el
contenido de la ROM en la RAM, los siguientes POKEs cambian la ROM de caracteres
y restauran la interrupción.

Cabe señalar que si bien los Bits 0-2 de este registro permiten el
control por software de algunas señales que determinan la configuración de la memoria que
es utilizado por el Commodore 64 en un momento dado, no son el único
factor determinante. Las señales también se pueden generar por medio de
cartuchos de expansión enchufables que están conectados al puerto de expansión, y
estos pueden cambiar el mapa de memoria.

Dos líneas ubicadas en el puerto de expansión se denominan JUEGO y EXROM.


Cuando se usa junto con las líneas controladas por software mencionadas
anteriormente, estas dos líneas de hardware pueden permitir que la ROM del cartucho reemplace
varios segmentos de ROM y / o RAM.

Las configuraciones posibles incluyen 8K de ROM de cartucho que se


cambiarán a $ 8000- $ 9FFF, para un programa de mejora BÁSICO; una ROM de cartucho de 8K
a $ A000- $ BFFF, reemplazando a BASIC, o en $ E000- $ FFFF, reemplazando el
Kernal, o un cartucho de 16k a $ 8000- $ C000.

Cuando se selecciona la ROM de cartucho para reemplazar el Kernal,


se ingresa un modo de emulador Max , que imita la especificación de la desafortunada Max
Machine, una máquina de juego que Commodore nunca produjo para la venta en
EE. UU. En este modo, solo los primeros 6K de Se utilizan RAM, no hay
acceso a la ROM de caracteres y los datos gráficos, como los datos de
puntos de caracteres, se asignan de 57344 ($ E000) a 8192 ($ 2000).
Puede obtener más información sobre el hardware en
la Guía de referencia del programador de Commodore 64 .

Los bits 3-5 de este registro tienen funciones conectadas con la


grabadora de casetes de datos . Estos son los siguientes:

Bit 3. Esta es la línea de salida de datos del casete. Esta línea está conectada
a la línea de escritura de datos de casete en el puerto de casete y se utiliza para
enviar los datos que se escriben en la cinta.

Bit 4. Este bit es la línea de detección de cambio de casete. Este bit permite a
un programa decir si uno de los botones que mueve la
grabadora está presionado o no . Si el interruptor de la grabadora está abajo, este
bit tendrá un valor de 1. Recuerde que el bit 4 del
registro de dirección de datos en la ubicación 0 debe contener un 0 para que este bit
refleje correctamente el estado del interruptor.

Bit 5. El bit 5 es el control del motor del casete. Establecer este bit en cero
permite que el motor gire cuando presiona uno de los botones en el
grabadora, si se establece en uno, no puede girar.

La mayoría de las veces, la configuración de este bit será controlada por la


rutina de interrupción que se utiliza para leer el teclado cada sesenta de
segundo. Si no se presiona ninguno de los botones del registrador, esa
rutina de interrupción apaga el motor y establece el enclavamiento en la
ubicación 192 ($ C0) a cero. Cuando se presiona un botón, si la
ubicación del enclavamiento es cero, el bit 5 de este registro se establece en cero para
encender el motor.

Cuando la ubicación del enclavamiento contiene un cero, la rutina de exploración de teclas


no le permitirá controlar la configuración de este bit del registro (y el
enclavamiento siempre se establece en cero cuando no se presiona ningún botón). En
Para obtener el control del motor, debe introducir un
valor distinto de cero en 192 después de presionar un botón en la grabadora. A
continuación, puede apagar el motor y volver a encenderlo como desee,
www.unusedino.de/ec64/technical/project64/mapping_c64.html 7/126
25/9/2020 Mapping The C64
manipulando este bit, siempre que un botón permanezca presionado.

2 $ 2 Sin
usar

3-4 $ 3- $ 4
Vector ADRAY1 : Rutina para convertir un número de punto flotante a
entero
con signo

Este vector apunta a la dirección de la rutina BASIC que convierte un número de punto flotante en un entero. En la versión actual de Kernal,
la dirección a la que apunta es 45482 ($ B1AA). El desmontaje de las
ROM indica que BASIC no utiliza este vector. Sin embargo, puede
ser de gran ayuda para el programador que desee utilizar datos
almacenados en formato de coma flotante. El parámetro que pasa el
comando USR solo está disponible en ese formato, por ejemplo.

Dado que es extremadamente difícil descifrar y usar un


número de punto flotante , la forma más sencilla de tratar con estos datos es usar las
rutinas de conversión que están integradas en BASIC para convertirlo en un
entero con signo de dos bytes. Esto se puede lograr saltando
directamente a la ROM BÁSICA, si conoce la ubicación de la rutina.
Por lo tanto, si la dirección cambia en futuras versiones de las 64 o
futuras computadoras Commodore, no tendrá que modificar su programa para
que funcione con ellas.

Consulte la entrada para el vector USR en 785 ($ 311) para obtener una explicación de
cómo usar esta rutina en relación con el comando USR.

5-6 $ 5- $ 6
Vector ADRAY2 : Rutina para convertir un número de entero a coma flotante

Este vector apunta a la dirección de la rutina BASIC que convierte


un entero en un número de coma flotante. Esta rutina se
encuentra actualmente en 45969 ($ B391). BASIC no parece hacer referencia a esta
ubicación. Está disponible para que lo utilice el programador que necesite realizar
dicha conversión para un programa en lenguaje de máquina que interactúe con
BASIC. Para obtener una explicación de cómo utilizar esta rutina en relación
con el comando USR, consulte la entrada del vector USR en 785 ($ 311).

7 $ 7 CHARAC
Carácter de búsqueda para escanear Entrada de texto BÁSICA

Esta ubicación y la siguiente son muy utilizadas por las rutinas BASIC que
escanean el texto que llega al búfer en 512 ($ 200), con el fin de
detectar caracteres significativos como comillas, comas, la dos puntos que
separan las declaraciones BASIC y el final de línea. Los valores ASCII de tales
caracteres especiales generalmente se almacenan aquí.

Esta ubicación también es utilizada como área de trabajo por otras rutinas BÁSICAS que
no implican escanear texto.

8 $ 8 ENDCHR
Carácter de búsqueda para terminación de estado de cuenta o cotización

Al igual que la ubicación 7, esta ubicación se utiliza como un byte de trabajo durante la
tokenización de una declaración BASIC. La mayoría de las veces, su valor es 0
o 34.

9 $ 9 TRMPOS
La posición de la columna del cursor antes de la última

pestaña o SPC TRMPOS es utilizada por TAB y SPC. La posición de la columna del cursor antes de
TAB o SPC se mueve aquí desde 211 ($ D3) y se usa para calcular
dónde termina el cursor después de invocar una de estas funciones.
Tenga en cuenta que el valor contenido aquí muestra la posición del cursor en
una línea lógica. Dado que una línea lógica puede tener hasta dos
líneas físicas , el valor almacenado aquí puede oscilar entre 0 y 79.

10 $ A VERCK
Flag: LOAD o VERIFY

BASIC usa una rutina Kernal para realizar LOAD o VERIFY


función, dependiendo de si el acumulador (.A) está configurado en 0 o 1
al ingresar a la rutina. BÁSICO establece el valor de VERCK en 0 para una
CARGA o 1 para una VERIFICACIÓN. Su contenido se pasa a la
rutina LOAD de Kernal , que a su vez lo almacena en la ubicación 147 ($ 93).

11 $ B COUNT
Índice en el búfer de entrada de texto / número de subíndices de matriz

Las rutinas que convierten el texto en el búfer de entrada a 512 ($ 200)


en líneas de tokes de programa ejecutables, y las rutinas que unen
estas líneas de programa, usan esta ubicación como un índice en el
área del búfer de entrada. Cuando
finaliza el trabajo de conversión de texto a tokens , el valor en esta ubicación es igual a la longitud del
línea tokenizada.

Las rutinas que construyen una matriz o ubican un elemento en una matriz utilizan
esta ubicación para calcular la cantidad de DIMensions solicitada y la
cantidad de almacenamiento necesaria para una matriz recién creada, o la cantidad de
subíndices especificados al hacer referencia a un elemento de matriz.

12 $ C DIMFLG
Banderas para las rutinas que ubican o construyen una matriz

Esta ubicación es utilizada como una bandera por las rutinas que crean una matriz o hacen
referencia a una matriz existente. Se utiliza para determinar si una
www.unusedino.de/ec64/technical/project64/mapping_c64.html 8/126
25/9/2020 Mapping The C64
variable está en una matriz, si la matriz ya ha sido
DIMensionada y si una nueva matriz debe asumir las
dimensiones predeterminadas .

13 $ D VALTYP
Indicador: tipo de datos (cadena o numérico)

Este indicador se utiliza internamente para indicar si los datos


sobre los que se opera son cadenas o numéricos. Un valor de 255 ($ FF) en esta ubicación
indica datos de cadena, mientras que un 0 indica datos numéricos. Esta
determinación se realiza cada vez que se localiza o se crea una variable.

14 $ E INTFLG
Plano: Tipo de datos numéricos (entero o coma flotante)

Si se determina que los datos que utiliza BASIC son numéricos, se


clasifican aquí como un número de coma flotante o como un
entero. Un 128 ($ 80) en esta ubicación identifica el número como un
entero, y un 0 indica un número de punto flotante.

15 $ F GARBFL
Indicador para LIST, recolección de basura y tokenización de programas

La rutina LIST usa este byte como indicador para avisarle cuando ha
llegado a una cadena de caracteres entre comillas. Luego imprimirá la cadena, en
lugar de buscar tokens de palabras clave BASIC.

La rutina de recolección de basura usa esta ubicación como una bandera para
indicar que la recolección de basura ya se ha intentado antes de agregar
una nueva cadena. Si aún no hay suficiente memoria,
aparecerá un mensaje SIN MEMORIA .

Esta ubicación también se usa como un byte de trabajo para el proceso de


convertir una línea de texto en el búfer de entrada BASIC (512, $ 200) en una
línea de programa vinculada de tokens de palabras clave BASIC.

16 $ 10 SUBFLG
Bandera: Referencia de subíndice a una matriz o llamada a función definida por el usuario (FN)

Esta bandera es utilizada por la rutina PTRGET que busca o crea una
variable, en el momento en que verifica si el nombre de una variable es
válido. Si se encuentra un paréntesis de apertura, este indicador se establece para
indicar que la variable en cuestión es una variable de matriz o
una función definida por el usuario.

Debe tener en cuenta que es perfectamente legal que una función definida por el usuario
(FN) tenga el mismo nombre que una variable de punto flotante. Además, también
es legal redefinir una función. El uso de un nombre FN en una
función ya definida da como resultado la nueva definición de la función.

17 $ 11 INPFLG
Bandera: ¿La entrada de datos es OBTENER, LEER o ENTRAR?

Dado que las palabras clave GET, INPUT y READ realizan funciones similares,
BASIC ejecuta algunas de las mismas instrucciones para las tres. Sin
embargo, también hay muchas áreas de diferencia, y esta bandera indica cuál
de las tres palabras clave se está ejecutando actualmente, de modo que BASIC
sabrá si ejecutar o no las instrucciones que se relacionan con las
áreas en las que los comandos difieren (152 ($ 98 ) = LEER, 64 ($ 40) = OBTENER,
0 = ENTRAR).

Como resultado, INPUT mostrará el? mensaje, hará eco de los caracteres
en la pantalla y esperará a que una línea completa de texto termine con un
retorno de carro. GET no da ningún aviso y acepta un carácter
Sin esperar. El carácter de dos puntos y la coma son datos válidos para
GET, pero INPUT y READ los tratan como delimitadores entre los datos.

Como cada comando tiene sus propios mensajes de error, esta bandera se usa para
determinar el mensaje apropiado para emitir en caso de error.

18 $ 12
Bandera TANSGN : Signo del resultado de la función TAN o SIN

Esta ubicación se utiliza para determinar si el signo del valor


devuelto por las funciones SIN o TAN es positivo o negativo.

Además, las rutinas de comparación numérica y de cadenas utilizan esta


ubicación para indicar el resultado de la comparación. Para una comparación
de la variable A con la variable B, el valor aquí será 1 si A es mayor
que B, 2 si A es igual a B, y 4 si a es menor que B. Si
se utilizó más de un operador de comparación para comparar las dos variables (por ejemplo,> = o
<=), el valor aquí será una combinación de valores anteriores.

19 $ 13 CHANNL
Número de canal de E / S actual (archivo lógico CMD)

Siempre que BASIC ingresa o emite datos, busca aquí para determinar
qué dispositivo de E / S está activo actualmente con el propósito de solicitar o
controlar la salida. Utiliza la ubicación 184 ($ B8) con el propósito de decidir desde
qué dispositivo colocar realmente la entrada o la salida.

Cuando
se utiliza el dispositivo de entrada predeterminado (número 0, el teclado) o el dispositivo de salida (número 3, la pantalla de visualización
un cero, y el formato de solicitud y salida será el
formato de salida de pantalla estándar .

Cuando se utiliza otro dispositivo, el número de archivo lógico (


número de canal CMD ) se colocará aquí. Esto permite que el sistema
www.unusedino.de/ec64/technical/project64/mapping_c64.html 9/126
25/9/2020 Mapping The C64
tenga que realizar algunos cambios sutiles en la forma en que realiza la
operación de E / S. Por ejemplo, si se usa TAB con el comando PRINT, los
caracteres del cursor derecho se usan si el dispositivo PRINTed es la pantalla.
De lo contrario, se generan espacios cuando el número aquí es distinto de cero
(se supone que no puede tabular una impresora como puede hacerlo en la
pantalla).

Asimismo, el? La solicitud de ENTRADA se suprime si el número de archivo aquí


es distinto de cero, al igual que el mensaje EXTRA IGNORED, y la entrada de un
retorno de carro por sí misma se ignora, en lugar de tratarse como una
cadena nula (""). Por lo tanto, al ABRIR la pantalla como un dispositivo y
emitir la instrucción CMD, puede forzar la supresión de?
pronto, y los otros efectos anteriores.

CMD coloca el nuevo número de archivo de salida aquí y llama al Kernal para
abrir el dispositivo para la salida, dejándolo ESCUCHANDO para la salida (como
el indicador READY, que se desvía al nuevo dispositivo).

Muchas rutinas restablecen esta ubicación y DES ESCUCHAN el dispositivo, derrotando


al CMD y una vez más enviando la salida a la pantalla. Si
se debe mostrar un mensaje de error , por ejemplo, esta ubicación se restablecerá
y el mensaje se mostrará en la pantalla. GET, GET #, INPUT,
INPUT # e PRINT # restablecerán esta ubicación después de que se
complete la E / S , redirigiendo efectivamente la salida de regreso a la pantalla. PRINT
y LIST son las únicas operaciones de E / S que no deshacen la CMD.

Esta ubicación también puede usarse para engañar a BASIC haciéndole creer que los datos
que está leyendo de la cinta en realidad se están ingresando en el
teclado en modo inmediato.

Para ver una técnica que utiliza un enfoque diferente para lograr
lo mismo para los usuarios de discos o cintas, consulte la ubicación 512 ($ 200), el
búfer del teclado.

20-21 $ 14- $ 15 LINNUM


Número de línea entero Valor

El número de línea de destino para GOTO, LIST, ON y GOSUB se almacena aquí en


formato entero de bytes bajos y bytes altos, al igual que el número de una línea BASIC
que se agregará o reemplazará.

LIST guarda el número de línea más alto para listar (o 65535 ($ FFFF) si el
programa se listará hasta el final) en esta ubicación.

GOTO prueba el número de línea de destino para ver si es mayor que el


número de línea que se está ejecutando actualmente. Si es mayor, GOTO comienza
su búsqueda de la línea objetivo en el número de línea actual. Si no es
mayor, GOTO debe buscar la línea de destino desde la primera línea
del programa. Es interesante notar que la prueba es
solo del byte más significativo. Por lo tanto, INT (TARGETLINE / 256) debe ser
mayor que INT (CURRENTLINE / 256) para que la búsqueda comience
con la línea actual, en lugar de al principio del programa.

PEEK, POKE, WAIT y SYS usan esta ubicación como puntero a la


dirección que es el tema del comando.

22 $ 16 TEMPPT
Puntero al siguiente espacio disponible en la pila de cadenas temporal

Esta ubicación apunta a la siguiente ranura disponible en la


pila de descriptores de cadena temporal ubicada en 25-33 ($ 19- $ 21). Dado que esa pila
tiene espacio para tres descriptores de tres bytes cada uno, esta ubicación apuntará
a 25 ($ 19) si la pila está vacía, a 28 ($ 1C) si hay una
entrada, a 31 ($ 1F) si hay dos entradas, ya 34 ($ 22) si la
pila está llena.

Si BASIC necesita agregar una entrada a la


pila de descriptores de cadena temporal , y esta ubicación tiene un 34, lo que indica que la pila está
llena, se emite el mensaje de error FÓRMULA DEMASIADO COMPLEJA. De lo contrario,
se agrega la entrada y se agregan tres a este puntero.

23-24 $ 17- $ 18 LASTPT


Puntero a la dirección de la última cadena en la
pila de cadenas temporal

Este puntero indica la última ranura utilizada en la


pila de descriptores de cadena temporal . Por lo tanto, el valor almacenado en 23 ($ 17) debe ser 3
menos que el almacenado en 22 ($ 16), mientras que 24 ($ 18) contendrá un 0.

25-33 $ 19- $ 21
Pila de descriptores TEMPST para cadenas temporales

La pila de descriptores de cadenas temporales contiene información sobre


cadenas temporales que aún no se han asignado a una
variable de cadena . Un ejemplo de una cadena temporal de este tipo es la
cadena literal "HELLO" en la declaración PRINT "HELLO".

Cada descriptor de tres bytes en esta pila contiene la longitud de la


cadena y sus ubicaciones de inicio y finalización, expresadas como
desplazamientos dentro del área de almacenamiento BASIC.

34-37 $ 22- $ 25 ÍNDICE


Varios punteros temporales y área de guardado

Esta área es utilizada por muchas rutinas BÁSICAS para contener punteros temporales
y resultados de cálculo.

38-42 $ 26- $ 2A RESHO


www.unusedino.de/ec64/technical/project64/mapping_c64.html 10/126
25/9/2020 Mapping The C64
Área de trabajo de multiplicación de punto flotante

Esta ubicación es utilizada por las rutinas BÁSICAS de multiplicación y división.


También lo utilizan las rutinas que calculan el tamaño del área
necesaria para almacenar una matriz que se está creando.

43-44 $ 2B- $ 2C TXTTAB


Puntero al inicio del texto del programa BASIC

Este puntero de dos bytes le permite al BASIC saber dónde está almacenado el texto del programa.
Por lo general, dicho texto se ubica a partir de 2049 ($ 801). Con este
puntero, es posible cambiar el área de texto del programa. Las
razones típicas para hacer esto incluyen:

1. Adaptar la configuración de la memoria a la de otras


computadoras Commodore . En computadoras PET y CBM de 32K, por ejemplo, memoria de pantalla
comienza en 32768 ($ 8000) y el texto BÁSICO comienza en 1025 ($ 401). Puede
emular esta configuración con el 64 con el siguiente
programa corto :

10 POKE 55,0: POKE 56,128: CLR: REM LOWER TOP OF MEMORY TO 32768
20 POKE 56576, PEEK (56576) Y 253: REM ENABLE BANK 2
30 POKE 53272 , 4: LA MEMORIA DE VISUALIZACIÓN DE TEXTO REM AHORA COMIENZA EN 32768
40 POKE 648,128: EL SISTEMA OPERATIVO REM IMPRIME A LA PANTALLA EN 32768 (128 * 256)
50 POKE 44,4: POKE 1024,0: REM MOVER INICIO DE BÁSICO A 1025 (4 * 256) +1)
60 POKE 792,193: REM DESHABILITAR RESTAURAR CLAVE
70 IMPRIMIR CHR $ (147); "AHORA CONFIGURADO COMO MASCOTA": NUEVO
80 REM VER TAMBIÉN ENTRADAS PARA LA UBICACIÓN 55, 56576 Y 648

Dicha reconfiguración puede ser útil para transferir programas desde el 64


al PET, o viceversa. Dado que el 64 reubica automáticamente el
texto del programa BASIC , puede cargar y listar programas PET aunque el
archivo de programa indique una dirección de carga que es diferente del
inicio 64 del BASIC. Sin embargo, el PET no tiene esta
función de reubicación automática y carga todos los programas BASIC en la
dirección de dos bytes indicada al principio del archivo de disco o cinta.

Entonces, si PET carga un programa 64 en su dirección inicial normal de


2049 ($ 801), no reconocerá su presencia porque espera que un
programa BÁSICO comience en 1025 ($ 401). Por lo tanto, si desea permitir que
un PET y 64 compartan un programa, debe reconfigurar el 64 para
inicie BASIC donde lo hace el PET, o reconfigure el PET para iniciar BASIC
donde lo hace el 64 (con un POKE 41,8: POKE 2048,0).

2. Elevar la ubicación más baja utilizada para el texto BÁSICO para crear
un área segura con poca memoria. Por ejemplo, si desea utilizar el
modo de gráficos de alta resolución, es posible que desee poner el inicio de la
memoria de la pantalla en 8192 ($ 2000). El moe de alta resolución requiere 8K de
memoria y no puede usar el 8K más bajo para este propósito porque
ya se está usando para las asignaciones de página cero.

Dado que el texto del programa BÁSICO normalmente comienza en 2048 ($ 801), esto significa
que solo tiene 6k para el texto del programa antes de que su programa se ejecute
en la memoria de la pantalla. Una forma de evitar esto es moviendo el inicio de
básico a 16385 ($ 4001) escribiendo en modo de entrada directa:

POKE 44,64: POKE 64 * 256,0: NUEVO

Otros usos pueden incluir apartar un área de almacenamiento para


datos de formas de sprites o conjuntos de caracteres definidos por el usuario.

3. Mantener dos o más programas en memoria simultáneamente. Al


cambiar este puntero, puede mantener más de un programa BASIC en la
memoria a la vez y alternar entre ellos.
Se pueden encontrar ejemplos de esta aplicación en el primer libro de PET / CBM de COMPUTE !,
páginas 66 y 163.

Esta técnica tiene varias ramificaciones que quizás sean de


uso más práctico.

a) Puede almacenar dos programas en la memoria simultáneamente para el propósito


de agregar uno al otro. Esta técnica requiere que los
números de línea de los dos programas no se superpongan. (Consulte Programación de
PET / CBM por Raeto Collin West, páginas 41-42, para una discusión de esta
técnica).

b) Puede tener dos programas en la memoria a la vez y usar el concepto en


(2) anterior para permitir una manera más fácil de crear un área segura con poca memoria.
El primer programa está en la línea que establece el inicio del
puntero BASIC en la dirección del segundo programa que se encuentra más arriba
en la memoria, y luego ejecuta ese segundo programa.

4. Dado que esta dirección se utiliza como la dirección del primer byte para
GUARDAR, puede guardar cualquier sección de la memoria cambiando este puntero a
indique la dirección de inicio y el puntero 45-46 ($ 2D- $ 2D) para
indicar la dirección del byte después del último byte que desea
guardar.

45-46 $ 2D- $ 2E VARTAB


Puntero al inicio del área de almacenamiento de variables BASIC

Esta ubicación apunta a la dirección que marca el final del


área de texto del programa BASIC y el comienzo del área de almacenamiento de variables.
Todas las variables que no son de matriz se almacenan aquí, al igual que los descriptores de cadena (para
la dirección del área donde se almacena el texto real de las cadenas,
consulte la ubicación 51 ($ 33)).

Se asignan siete bytes de memoria para cada variable. Los dos primeros
www.unusedino.de/ec64/technical/project64/mapping_c64.html 11/126
25/9/2020 Mapping The C64
bytes se utilizan para el nombre de la variable, que consta de ASCII
valor de las dos primeras letras del nombre de la variable. Si el
nombre de la variable es una sola letra, el segundo byte contendrá un cero.

Se puede establecer el séptimo bit de uno o ambos bytes (lo que


sumaría 128 al valor ASCII de la letra). Esto indica el
tipo de variable. Si ninguno de los bytes tiene el séptimo bit establecido, la variable
es el tipo de coma flotante regular. Si solo el primer byte tiene su
séptimo bit establecido, la variable es una cadena. Si solo el segundo byte
tiene su séptimo bit establecido, la variable es una función definida (FN). Si
ambos bytes tienen el séptimo bit establecido, la variable es un número entero.

El uso de los otros cinco bytes depende del tipo de variable. UNA
La variable de punto flotante utilizará los cinco bytes para almacenar el valor de
la variable en formato de punto flotante. Un número entero tendrá su valor
almacenado en el tercer y cuarto bytes, el byte alto primero, y los otros
tres no se utilizarán.

Una variable de cadena usará el tercer byte para su longitud y el


cuarto y quinto bytes para un puntero a la dirección del
texto de cadena , dejando los dos últimos bytes sin usar. Tenga en cuenta que el
texto de una cadena de texto al que se apunta se encuentra en la parte del
programa BASIC donde se asigna un valor a la cadena por primera vez, o en el
área de almacenamiento de texto de cadena a la que apunta la ubicación 51 ($ 33).

Una definición de función utilizará el tercer y cuarto bytes para una


puntero a la dirección en el texto del programa BÁSICO donde
comienza la definición de la función . Utiliza el quinto y sexto bytes como puntero a
la variable dependiente (la X de FN A (X)). No se
utiliza el byte final .

Saber algo sobre cómo se crean las variables puede ayudar a su


programación BÁSICA . Por ejemplo, puede ver que las variables enteras sin matrices
no ocupan menos espacio que las variables de coma flotante, y dado que la mayoría de los
comandos BASIC convierten los enteros en coma flotante, tampoco
ofrecen una ventaja de velocidad y, en muchos casos, ralentizarán
el programa. abajo. Sin embargo, como se verá a continuación, las matrices de números enteros pueden
ahorrar una cantidad considerable de espacio.

Las variables se almacenan en el orden en que se crean.


Asimismo, cuando BASIC va a buscar una variable, comienza su búsqueda
al principio de esta área. Si las variables de uso común se definen
al final del programa y, por lo tanto, están al final de esta área,
tomará más tiempo encontrarlas. Puede ayudar a la velocidad de ejecución del programa a
definir las variables que se utilizarán con más frecuencia justo al
principio del programa.

Además, recuerde que una vez creadas, las variables no desaparecen durante la
ejecución del programa. Incluso si nunca se vuelven a utilizar, todavía ocupan
espacio en el área de almacenamiento de variables y ralentizan la rutina
que se utiliza para buscar variables a las que se hace referencia.

Otro punto a considerar sobre el orden en el que se definen las variables


es que las matrices se crean en un área separada de memoria que comienza
al final del área de variables sin matrices. Por lo tanto, cada vez que se
crea una variable que no sea de matriz, todas las matrices deben moverse siete
bytes más arriba en la memoria para dejar espacio para la nueva variable.
Por lo tanto, puede ayudar al rendimiento evitar definir
variables que no sean de matriz después de definir las matrices.

Este puntero se restablecerá a un byte después del final del


texto del programa BASIC cada vez que ejecute las instrucciones CLR, NEW, RUN o
LOAD. Agregar o modificar una sentencia BASIC tendrá el mismo
efecto, porque las sentencias BASIC con números más altos deben moverse
en la memoria para dejar espacio para las nuevas declaraciones y, por lo tanto, puede
sobrescribir el área de almacenamiento de variables. Esto significa que si desea
verificar el valor de una variable después de detener un programa, solo puede
hacerlo antes de modificar el programa.

La excepción a lo anterior es cuando el comando LOAD se emite desde un


programa. El propósito de no restablecer este puntero en tal caso es
permitir el encadenamiento de programas haciendo que un programa cargue y luego
ejecute el siguiente (esa es también la razón por la que una CARGA emitida desde un programa provoca una
EJECUCIÓN desde el principio del programa). Esto permite que el segundo
programa comparta variables con el primero. Sin
embargo, hay problemas con esto. Algunas funciones y descriptores de variables de cadena
las definiciones tienen sus punteros establecidos en áreas dentro del texto del programa.
Cuando este texto se reemplaza por una carga, estos punteros ya no son
válidos, lo que dará lugar a errores si se hace
referencia al valor de cadena o FN . Y si el área de texto del segundo programa es más grande que la
del primero, el segundo programa sobrescribirá algunas de las
variables del primer programa y sus valores se perderán.

La capacidad de encadenar programas cortos es un vestigio de los días del


PET 8K, para el cual se escribió este BASIC, pero con la
memoria enormemente aumentada del 64, el encadenamiento de programas no debería ser necesario.

También debe tener en cuenta que SAVE utiliza este puntero como la dirección del
byte después del último byte para SAVE.

47-48 $ 2F- $ 30 ARYTAB


Puntero al inicio del área de almacenamiento de matriz BÁSICA

Esta ubicación apunta a la dirección del final del


almacenamiento de variables sin matriz y al comienzo del almacenamiento de variables de matriz. El formato para el
almacenamiento de la matriz es el siguiente:

Los primeros dos bytes contienen el nombre de la matriz. El formato y los


www.unusedino.de/ec64/technical/project64/mapping_c64.html 12/126
25/9/2020 Mapping The C64
patrones de bits altos son los mismos que para las variables sin matriz (consulte 45 ($ 2D) más arriba),
excepto que no hay equivalente a la definición de la función.

Luego viene un desplazamiento de dos bytes al comienzo de la siguiente matriz,


primero el byte bajo . Entonces hay un valor de un byte para el número de
dimensiones de la matriz (por ejemplo, 2 para una matriz bidimensional como A (x, y)). Ese
byte es seguido por pares de bytes que contienen el valor de cada
dimensión de la matriz + 1 (DIMensionar una matriz siempre deja espacio para 0, por lo que
se puede usar A (0) ).

Finalmente vienen los valores de las propias variables. El formato de


estos valores es el mismo que el de los valores sin matriz, pero cada valor solo
ocupa el espacio necesario; es decir, las variables de coma flotante utilizan
cinco bytes cada una, los números enteros dos bytes y los descriptores de cadena de tres
bytes cada una.

Recuerde que, al igual que con la cadena sin matriz, el texto de la cadena real se
almacena en otro lugar, en el área que comienza en la ubicación señalada
en 51-52 ($ 33- $ 34).

49-50 $ 31- $ 32 CADENA


Puntero al final del área de almacenamiento de la matriz BASIC (+1) y al inicio de la
RAM libre

Esta ubicación apunta a la dirección del final del


espacio de almacenamiento de la matriz BASIC y el inicio de la RAM libre. Dado que el texto de la cadena comienza en la parte superior
de la memoria y se construye hacia abajo, esta ubicación también se puede considerar
como la última dirección posible del área de almacenamiento de la cadena. La definición de nuevas
variables empuja este puntero hacia arriba, hacia la última cadena de texto.

Si una cadena para la que se está asignando espacio cruza este


límite hacia el área de almacenamiento de la matriz, se realiza la recolección de basura
y , si aún no hay suficiente espacio, se produce un error FUERA DE MEMORIA.
FRE realiza la recolección de basura y devuelve la diferencia entre
las direcciones señaladas aquí y la dirección del final del
almacenamiento de texto de cadena señalado por la ubicación 51 ($ 33).

51-52 $ 33- $ 34 FREETOP


Puntero a la parte inferior del área de almacenamiento de texto de cadena

Este puntero marca el final actual del área de texto de cadena y la


parte superior de la RAM libre (las cadenas se crean desde la parte superior de la memoria hacia abajo).
Se agregan textos de cadena adicionales en el área debajo de la dirección
indicada aquí. Una vez agregados, este puntero se baja para
apuntar debajo del texto de cadena recién agregado. La
rutina de recolección de basura (que también es llamada por FRE) reajusta este puntero hacia arriba.

Mientras que las rutinas de encendido / reinicio establecen este puntero en la parte superior de la RAM,
el comando CLR establece este puntero al final de la memoria BASIC, como se
indica en la ubicación 55 ($ 37). Esto permite al usuario reservar un
área de la memoria BÁSICA que no será perturbada por el programa, como se
detalla en la ubicación 55 ($ 37).

53-54 $ 35- $ 36 FRESPC


Puntero temporal para cadenas

Se utiliza como un puntero temporal a la cadena más actual agregada


por las rutinas que crean cadenas o las mueven en la memoria.

55-56 $ 37- $ 38 MEMSIZ


Puntero a la dirección más alta utilizada por BASIC

La rutina de encendido / reinicio prueba cada byte de RAM hasta que llega a
la ROM BASIC y establece este puntero en la dirección del byte más alto
de RAM consecutiva encontrado (40959, $ 9FFF).

Hay dos circunstancias bajo las cuales este puntero puede cambiarse
después del encendido para reflejar una dirección más baja que la parte superior real de la
RAM consecutiva:

1. Los usuarios pueden desear bajar este puntero ellos mismos, para
reservar un área de RAM libre que BASIC no lo molestará. Por
ejemplo, para reservar un área de 1K en la parte superior de BASIC, comience su
programa con la línea:

POKE 56, PEEK (56) -4: CLR

El CLR es necesario para asegurarse de que el texto de la cadena comience debajo de


su área segura.

Es posible que desee almacenar programas en lenguaje de máquina, sprites o


conjuntos de caracteres alternativos en dicha área. Para las dos últimas aplicaciones,
sin embargo, tenga en cuenta la limitación del rango de direccionamiento de 16K del
Chip VIC-II. Si no asigna el VIC-II a un banco que no sea el
banco de memoria predeterminado de 0-16383 ($ 0- $ 3FFF), debe bajar la parte superior de la
memoria por debajo de 16383 ($ 3FFF) si desea los datos de su sprite o personaje
área dentro de su rango de direccionamiento.

2. Luego se abre el dispositivo RS-232 (número 2), este puntero y el


puntero al final de la RAM del usuario en 643 se reducen en 512 bytes
para crear dos búferes de 256 bytes, uno para entrada y el otro para
salida.

Dado que el contenido de estos búferes sobrescribirá cualquier variable en


la parte superior de la memoria, se emite un comando CLR en el momento en que se
abre el dispositivo 2 . Por lo tanto, el dispositivo RS-232 debe abrirse antes de definir
cualquier variable, y antes de reservar un área segura para
programas de lenguaje de máquina u otros usos, como se describe anteriormente.
www.unusedino.de/ec64/technical/project64/mapping_c64.html 13/126
25/9/2020 Mapping The C64

57-58 $ 39- $ 3A CURLIN


Número de línea BASIC actual

Esta ubicación contiene el número de línea de la instrucción BASIC que se


está ejecutando actualmente, en formato LSB / MSB. Un valor de 255 ($ FF) en la
ubicación 58 ($ 3A), que se traduce en un número de línea de 65280 o superior
(muy por encima del límite de 63999 para una línea de programa), significa que BASIC está
actualmente en modo inmediato, en lugar de RUN. modo.

Las palabras clave BASIC que son ilegales en el modo directo marcan 58 ($ 3A) para
determinar si este es el modo actual o no.

Cuando está en modo RUN, esta ubicación se actualiza a medida que se abre cada nueva línea BÁSICA.
buscado para su ejecución. Por lo tanto, se podría agregar una función TRACE
desviando el vector en 776 ($ 308), que apunta a la rutina que
ejecuta el siguiente token, a una rutina escrita por el usuario que imprime el
número de línea indicado por esta ubicación antes de saltar a la
ejecución del token. rutina. (LISTAR la línea en sí sería algo más difícil,
porque LIST usa muchas ubicaciones de la página 0 que tendrían que ser
preservadas y restauradas después).

Este número de línea es usado por BREAK y los mensajes de error para mostrar dónde se
detuvo la ejecución del programa. El valor aquí se copia a 59 ($ 3B) mediante
STOP, END y la tecla de parada BREAK, y CONT.

59-60 $ 3B- $ 3C OLDLIN


Número de línea BÁSICO anterior

Cuando finaliza la ejecución del programa, el último número de línea ejecutado se almacena
aquí y CONT se restaura a la ubicación 57 ($ 39).

61-62 $ 3D- $ 3E OLDTXT


Puntero a la dirección de la instrucción BASIC actual

Esta ubicación contiene la dirección (no el número de línea) del texto


de la instrucción BASIC que se está ejecutando. El valor de TXTPTR
(122, $ 7A), el puntero a la dirección del carácter de texto BÁSICO que
se está escaneando actualmente, se almacena aquí cada vez que
comienza la ejecución de una nueva línea BÁSICA .

END, STOP y la tecla STOP BREAK guardan el valor de TXTPTR aquí, y


CONT restaura este valor a TXTPTR. CONT no continuará si 62
($ 3E) ha sido cambiado a cero por una CARGA, una modificación al
texto del programa, o por rutinas de error.

63-64 $ 3F- $ 40 DATLIN


Número de línea de DATOS actual

Esta ubicación contiene el número de línea de la declaración de DATOS actual que se


está READ. Cabe señalar que esta información no se utiliza para
determinar de dónde se lee el siguiente elemento de DATOS (ese es el trabajo del
puntero en 65-66 ($ 41- $ 42) a continuación). Pero si
ocurre un error con respecto a los DATOS, este número se moverá a 57 ($ 39), de modo que el
mensaje de error mostrará que el error ocurrió en la línea que contiene
la instrucción DATA, en lugar de en la línea que contiene la
instrucción READ . .

65-66 $ 41- $ 42 DATPTR


Puntero a la dirección del elemento de datos actual

Esta ubicación apunta a la dirección (no al número de línea) dentro del


área de texto del programa BÁSICO donde los DATOS se están LEYENDO actualmente. RESTORE
establece este puntero de nuevo en la dirección indicada por el inicio del
puntero BASIC en la ubicación 43 ($ 2B).

El programa de ejemplo a continuación muestra cómo


se puede cambiar el orden en el que se LEEN las declaraciones de DATOS utilizando este puntero. La dirección actual de
la instrucción antes de la instrucción DATA se almacena en una variable y
luego se usa para cambiar este puntero.

10 A1 = PEEK (61): A2 = PEEK (62)


20 DATOS ESTOS DATOS SE UTILIZARÁN SEGUNDO
30 B1 = PEEK (61): B2 = PEEK (62)
40 DATOS ESTE DATOS SE UTILIZARÁN PRIMERO
50 C1 = PEEK (61 ): C2 = PEEK (62)
60 DATOS ESTE DATO SE UTILIZARÁ TERCER
70 POKE 65, B1: POKE 66, B2: LEER A $: IMPRIMIR UN $
80 POKE 65, A1: POKE 66, A2: LEER A $: IMPRIMIR $
90 POKE 65, C1: POKE 66, C2: LEER UN $ : PRINT A $

67-68 $ 43- $ 44 INPPTR


Puntero en la fuente de información GET, READ o INPUT

READ, INPUT y GET usan esto como un puntero a la dirección de la


fuente de datos entrantes, como declaraciones DATA, o el
búfer de entrada de texto en 512 ($ 200).

69-70 $ 45- $ 46 VARNAM


Nombre de la variable BÁSICA

actual El nombre de la variable actual que se está buscando se almacena aquí, en el


mismo formato de dos bytes que en el área de almacenamiento del valor de la variable ubicada en
la dirección señalada por 45 ($ 2D). Consulte esa ubicación para obtener una
explicación del formato.

71-72 $ 47- $ 48 VARPNT


Puntero al valor de la variable BASIC actual
www.unusedino.de/ec64/technical/project64/mapping_c64.html 14/126
25/9/2020 Mapping The C64

Esta ubicación apunta a la dirección del descriptor de la


variable BASIC actual (consulte la ubicación 45 ($ 2D) para conocer el formato de un
descriptor de variable ). Específicamente, apunta al byte justo después del
nombre de la variable de dos caracteres.

Durante una llamada FN, esta ubicación no apunta a la


variable dependiente (la A de FN A), por lo que una variable real con el mismo nombre
no cambiará su valor por la llamada.

73-74 $ 49- $ 4A FORPNT


Puntero temporal a la variable de índice utilizada por FOR

La dirección de la variable BASIC que es el tema de un FOR / NEXT


El bucle se almacena primero aquí, pero luego se inserta en la pila. Eso
deja esta ubicación libre para que la utilicen como área de trabajo declaraciones
como INPUT, GET, READ, LIST, WAIT, CLOSE, LOAD, SAVE, RETURN y GOSUB.

Para obtener una descripción de las entradas de la pila realizadas por FOR, consulte la ubicación 256
($ 100).

75-76 $ 4B- $ 4C OPPTR


Desplazamiento de la tabla del operador matemático

Esta ubicación se utiliza durante la evaluación de


expresiones matemáticas para mantener el desplazamiento del operador matemático actual en
una tabla de operador. También se utiliza como área de almacenamiento para el puntero a
la dirección del texto del programa que se está leyendo actualmente.

77 $ 4D OPMASK
Mask para operación de comparación

La rutina de evaluación de expresiones crea aquí una máscara que le permite


saber si la comparación actual en la operación es una comparación menor que (1),
igual (2) o mayor que (4).

78-79 $ 4E- $ 4F DEFPNT


Puntero al descriptor FN actual

Durante la definición de función (DEF FN), esta ubicación se utiliza como puntero
al descriptor que se crea. Durante la ejecución de la función (FN)
apunta al descriptor FN en el que se deben
guardar los resultados de la evaluación .

80-82 $ 50- $ 52 DSCPNT


Puntero temporal al descriptor de cadena actual

Las rutinas de asignación y manejo de cadenas usan los dos primeros bytes como
un puntero temporal al descriptor de cadena actual y el tercero para
contener el valor de la longitud de la cadena.

83 $ 53 FOUR6
Constante para recolección de basura

La constante contenida aquí permite a las rutinas de recolección de basura saber


si se está recolectando un descriptor de cadena de tres o siete bytes.

84-86 $ 54- $ 56 JMPER


Saltar a la instrucción de función

El primer byte es la instrucción 6502 JMP ($ 4C), seguida de la


dirección de la función requerida tomada de la tabla en 41042
($ A052).

87-96 $ 57- $ 60
BÁSICO Área de trabajo numérica

Esta es un área de trabajo muy ocupada, utilizada por muchas rutinas.

97-102 $ 61- $ 66 FAC1


Acumulador de punto flotante # 1

El acumulador de punto flotante es fundamental para la ejecución de cualquier


operación matemática BÁSICA. Se utiliza en la conversión de
números enteros a números de coma flotante, cadenas a números de coma flotante
y viceversa. Los resultados de la mayoría de las evaluaciones se almacenan en esta
ubicación.

El formato interno de los números de coma flotante no es particularmente fácil


de entender (o explicar). En términos generales, el número se divide
en la mantisa normalizada, que representa un número entre 1 y
1.99999 ..., y un valor de exponente, que representa una potencia de 2.
Multiplicar la mantisa por 2 elevado al valor del exponente
te da el valor del número de coma flotante.

Afortunadamente, el intérprete BASIC contiene muchas rutinas para la


manipulación y conversión de números de coma flotante, y
el usuario puede llamar a estas rutinas. Vea las entradas para las ubicaciones 3
y 5

El acumulador de punto flotante # 1 se puede dividir en las


siguientes ubicaciones:

97 $ 61 FACEXP
Acumulador de punto flotante # 1: Exponente

Este exponente representa la potencia más cercana de dos al número, con


129 agregado para tener cuidado del problema de signos para exponentes negativos. Se
www.unusedino.de/ec64/technical/project64/mapping_c64.html 15/126
25/9/2020 Mapping The C64
utiliza un exponente de 128 para el valor 0; un exponente de 129 representa
2 elevado a 0, o 1; un exponente de 130 representa 2 elevado a la primera
poder, o 2; 131 es 2 al cuadrado, o 4; 132 es 2 al cubo, o 8; y así.

98-101 $ 62- $ 65 FACHO


Acumulador de punto flotante # 1: Mantisa

Se puede suponer que el dígito más significativo es un 1 (recuerde que el


rango de la mantisa es de 1 a 1.99999 ...) cuando
se almacena un número de punto flotante en una variable. El primer bit se utiliza para el signo del
número y los otros 31 bits de la mantisa de cuatro bytes contienen los
otros dígitos significativos.

Los primeros dos bytes (98-99, $ 62- $ 63) de esta ubicación contendrán el
resultado entero con signo de una conversión de punto flotante a entero, en
orden de byte alto y byte bajo.

102 $ 66 FACSGN
Acumulador de punto flotante # 1: Señal

Un valor de 0 aquí indica un número positivo, mientras que un valor de 255


($ FF) indica un número negativo.

103 $ 67 SGNFLG
Número de términos en una evaluación en serie

Esta ubicación es utilizada por las rutinas de evaluación de fórmulas matemáticas. Se


indica el número de evaluaciones independientes que se deben hacer para
resolver una expresión compleja abajo a un solo término.

104 $ 68 BITS
Acumulador de coma flotante # 1: Dígito de desbordamiento

Esta ubicación contiene el byte de desbordamiento. El byte de desbordamiento se utiliza


en un paso intermedio de conversión de un entero o una cadena de texto
a un número de coma flotante.

105-110 $ 69- $ 6E FAC2


Acumulador de punto flotante # 2

Un segundo acumulador de punto flotante, utilizado junto con el


acumulador de punto flotante n . ° 1 en la evaluación de productos, sumas,
diferencias; en resumen, cualquier operación que requiera más de un valor.
El formato de este acumulador es el mismo que el de FAC1.

105 $ 69 ARGEXP
Acumulador de punto flotante # 2: Exponente

106-109 $ 6A- $ 6D ARGHO


Acumulador de punto flotante # 2: Mantisa

110 $ 6E ARGSGN
Acumulador de punto flotante # 2: Signo

111 $ 6F ARISGN
Resultado de una comparación firmada del acumulador # 1 al acumulador n. ° 2

Se utiliza para indicar si los dos acumuladores de punto flotante tienen


o signos distintos. Un 0 indica signos similares, un 255 ($ FF) indica
signos diferentes.

112 $ 70 FACOV
Byte de
mantisa de orden inferior del acumulador de coma flotante # 1 (para
redondeo)
Si la mantisa del número de coma flotante tiene
cifras más significativas de las que se pueden contener en cuatro bytes, las cifras menos significativas
se colocan aquí. Se utilizan para ampliar la precisión de las
operaciones matemáticas intermedias y para redondear a la cifra final.

113-114 $ 71- $ 72
Puntero de evaluación de la serie FBUFPT

Esta ubicación apunta a la dirección de una tabla temporal de valores


construida en el área de RAM libre para la evaluación de fórmulas. Tambien es
se utiliza para diversos fines como un área de trabajo TI $, un
puntero de configuración de cadena y un espacio de trabajo para la evaluación del tamaño de una matriz.

Aunque esto está etiquetado como un puntero al búfer de cinta en la


Guía de referencia del programador, el desmontaje de la ROM BÁSICA no revela ninguna
referencia a esta ubicación para ese propósito (consulte 178 ($ B2) para el puntero
al búfer de cinta).

115-138 $ 73- $ 8A CHRGET


Subrutina: Obtener el siguiente carácter de texto BÁSICO

Esta es en realidad una subrutina de lenguaje de máquina, que en el momento de un


arranque en frío BÁSICO (como cuando se enciende la alimentación) se copia de
MOVCHG (58274, $ E3A2) en la ROM a esta ubicación de página cero.

CHRGET es una rutina crucial que BASIC usa para leer caracteres de texto,
como el texto del programa BASIC que se está interpretando. Se
coloca en la página cero para que la rutina se ejecute más rápido. Dado que realiza un
seguimiento de la dirección del carácter que se lee dentro de la rutina
misma, la rutina debe estar en la RAM para actualizar ese puntero.
El puntero a la dirección del byte que se está leyendo actualmente es realmente
el operando de una instrucción LDA. Cuando se ingresa desde CHRGET, la
rutina incrementa el puntero modificando el operando en TXTPTR
www.unusedino.de/ec64/technical/project64/mapping_c64.html 16/126
25/9/2020 Mapping The C64
(122, $ 7A), permitiendo así que se lea el siguiente carácter.

Entry at CHRGOT (121, $79) allows the current character to be read


again. The CHRGET routine skips spaces, sets the various flags or the
status register (.P) to indicate whether the character read was a
digit, statement terminator, or other type of character, and returns
with the retrieved character in the Accumulator (.A).

Since CHRGET is used to read every BASIC statement before it is


executed, and since it is in RAM, and therefore changeable, it makes a
handy place to intercept BASIC to add new features and commands (and
in the older PET line, it was the only way to add such features).
Diversion of the CHRGET routine for this purpose is generally referred
to as a wedge.

Dado que una cuña puede ralentizar enormemente la velocidad de ejecución, la mayor parte del tiempo
se configura para que realice sus funciones de preprocesamiento solo cuando
en modo directo o inmediato. El ejemplo más conocido de este tipo de
brechas es el programa "Soporte universal de DOS" que permite una
comunicación más sencilla con el canal de comando de la unidad de disco.

Como se trata de una rutina tan central, a


continuación se proporciona una lista de desmontaje para comprender mejor cómo funciona.

115 $ 73 CHRGET INC TXTPTR; incremento del byte bajo de TXTPTR


117 $ 75 BNE CHRGOT; si el byte bajo no es 0, omita el siguiente
119 $ 77 INC TXTPTR + 1; incremento del byte alto de TXTPTR
121 $ 79 CHRGOT LDA; carga el byte desde donde apunta TXTPTR
; la entrada aquí no actualiza TXTPTR
,; lo que le permite volver a leer el byte antiguo
122 $ 7A TXTPTR $ 0207; el puntero es realmente el operando LDA
; TXTPTR + 1 puntos a 512-580 ($ 200- $ 250)
; al leer del búfer de entrada
; en modo directo
124 $ 7C POINTB CMP # $ 3A; bandera de transporte activada si> número ASCII 9
126 $ 7E BCS EXIT; el carácter no es un número - salida
128 $ 80 CMP # $ 20; si es un espacio ASCI ...
130 $ 82 BEQ CHRGET; ignórelo y obtenga el siguiente carácter
132 $ 84 SEC; prepárese para restar
133 $ 85 SBC # $ 30; ASCII 0-9 están entre 48-57 ($ 30- $ 39)
135 $ 87 SEC; prepárate para restar de nuevo
136 $ 88 SBC # $ D0; si <ASCII 0 (57, $ 39) entonces el acarreo se establece
138 $ 8A EXIT RTS; el acarreo es claro solo para el numeral al regresar

El acumulador (registro .A) contiene el carácter que se leyó al


salir de la rutina. Los bits del registro de estado (.P) que se pueden probar
al salir son:

Carry Clear si el carácter era un dígito ASCII 0-9.


Carry Set, de lo contrario.
Ajuste a cero solo si el carácter era un terminador de declaración 0 o
dos puntos ASCII, 58 ($ 3A).
Zero Clear, de lo contrario.

Una técnica de inserción de cuñas es cambiar el INC $ 7A de CHRGET a una


CUÑA JMP , hacer que su cuña actualice el TXTPTR y luego JSR CHRGOT.
Otra es cambiar el CMP # $ 3A en la ubicación 124 ($ 7C), que he
etiquetado como POINTB, a un JMP WEDGE, hacer su procesamiento de wedge y luego
salir a través de la versión ROM de POINTB, que se encuentra en 48283
($ E3AB). Para obtener información más detallada sobre las cuñas, consulte Programación
del PET / CBM, Raeto Collin West, páginas 365-68.

Si bien el wedge es una técnica buena y rápida para agregar nuevos comandos,
existe un método mucho más elegante para realizar esta tarea en el
VIC-20 y 64 sin ralentizar el BASIC hasta el punto que lo hace el wedge
. Consulte las entradas para el área de vector de RAM BÁSICA en 768-779
($ 300- $ 30B) para obtener más detalles.

139-143 $ 8B- $ 8F Valor inicial de la


función RNDX RND

Esta ubicación contiene el valor de punto flotante de cinco bytes devuelto por la
función RND. Inicialmente se establece en un valor semilla copiado de ROM
(los cinco bytes son 128, 79, 199, 82, 88 - $ 80, $ 4F, $ C7, $ 52, $ 58).

Cuando se llama a la función RND (X), el valor numérico de X no


afecta el número devuelto, pero su signo sí. Si X es igual a 0,
RND genera un valor semilla a partir de temporizadores de hardware a nivel de chip. Si X es un
número positivo, RND (X) devolverá el siguiente número en una
secuencia aritmética . Esta secuencia continúa durante tanto tiempo sin
repetirse, y da una distribución de números tan uniforme que
puede considerarse aleatoria. Si X es negativo, el valor semilla es
cambiado a un número que corresponde a una
representación de coma flotante codificada del número X en sí.

Dado un valor de semilla en particular,


siempre se devolverá la misma serie pseudoaleatoria de números . Esto puede ser útil para fines de depuración,
pero no cuando desee tener números verdaderamente aleatorios.

El método tradicional de Commodore para seleccionar una semilla aleatoria es mediante el


uso de la expresión RND (-TI), principalmente porque RND (0) no funcionó
correctamente en los primeros PET. Si bien el formulario RND (0) tampoco funciona
bien en el 64 (consulte la ubicación 57495 ($ E097)), la expresión
RND (-RND (0)) puede producir un valor de inicialización más aleatorio.

Rango de ubicación: 144-255 ($ 90- $ FF)


Área de almacenamiento de trabajo Kernal
www.unusedino.de/ec64/technical/project64/mapping_c64.html 17/126
25/9/2020 Mapping The C64

Esta es el área de almacenamiento de página cero para Kernal. El usuario debe


tener en cuenta qué efecto tendrá cambiar una ubicación aquí en
el funcionamiento de las funciones de Kernal antes de realizar tales cambios.

Al encender, este rango de ubicaciones se llena primero con ceros y


luego se inicializa a partir de los valores almacenados en la ROM según sea necesario.

144 $ 90 ESTADO
Palabra de estado de E / S Kernal (ST)

Las rutinas Kernal que abren canales de E / S o realizan funciones de entrada / salida
verifican y actualizan esta ubicación. El valor aquí es casi
siempre el mismo que el devuelto a BASIC mediante el uso de la
variable reservada ST. Tenga en cuenta que la sintaxis BÁSICA no permitirá una asignación como
como ST = 4. A continuación se muestra una tabla de códigos de estado para casetes y dispositivos seriales
:

Casete:
Bit 2 (Valor de bit de 4) = Bloque corto
Bit 3 (Valor de bit de 8) = Bloque largo
Bit 4 (Valor de bit de 16) = Error irrecuperable (Leer ), falta de coincidencia
Bit 5 (Valor de bit de 32) = Error de suma de comprobación
Bit 6 (Valor de bit de 64) = Fin del archivo

Dispositivos serie:
Bit 0 (Valor de bit de 1) = Tiempo de espera (Escritura)
Bit 1 (Valor de bit de 2 ) = Tiempo de espera (lectura)
Bit 6 (Valor de bit de 64) = EOI (Finalizar o identificar)
Bit 7 (Valor de bit de 128) = Dispositivo no presente

Probablemente el bit más útil para probar es el Bit 6 (final del archivo). Cuando se
usa la instrucción GET para leer bytes individuales de un archivo, el
La declaración IF ST AND 64 será verdadera si ha llegado al final del
archivo.

Para conocer los códigos de estado del dispositivo RS-232, consulte la entrada de la ubicación 663
($ 297).

145 $ 91
Bandera STKEY : ¿Se presionó la tecla STOP?

Esta ubicación se actualiza cada 1/60 de segundo durante la ejecución de la


rutina IRQ que lee el teclado y actualiza el reloj jiffy.

Aquí se coloca el valor de la última fila de la matriz del teclado. Esa


fila contiene la tecla STOP, y aunque esta ubicación se usa
principalmente para detectar cuándo se ha presionado esa tecla, también puede detectar
cuándo se ha presionado alguna de las otras teclas en esa fila de la matriz
.

Al leer la matriz del teclado, un bit puesto a 1 significa que no se


ha pulsado ninguna tecla , mientras que un bit puesto a 0 indica que se ha pulsado una tecla.
Por lo tanto, los siguientes valores indican las pulsaciones de teclas que se detallan a
continuación:

255 $ FF = ninguna tecla presionada


254 $ FE = 1 tecla presionada
253 $ FD = (flecha izquierda) tecla presionada
251 $ FB = CTRL tecla presionada
247 $ F7 = 2 tecla presionada
239 $ EF = barra espaciadora presionada
223 $ DF = Tecla del logotipo de Commodore presionada
191 $ BF = Tecla Q presionada
127 $ 7F = Tecla STOP presionada Los

propietarios de VIC notarán que la matriz del teclado del 64 es muy diferente
a la de VIC. Una de las ventajas de esta diferencia es que
puede probar la tecla STOP siguiendo una lectura de esta ubicación con una
instrucción BPL, lo que provocará una bifurcación en cualquier momento que se
presione la tecla STOP.

146 $ 92
Constante de tiempo de SVXT para lecturas de cinta

Esta ubicación se utiliza como una constante de tiempo ajustable para lecturas de cinta,
que se puede cambiar para permitir una ligera variación de velocidad entre
cintas.

147 $ 93
Bandera VERCK para rutina de carga: 0 = CARGAR, 1 = VERIFICAR

La misma rutina Kernal puede realizar una CARGA o VERIFICAR, dependiendo


del valor almacenado en el acumulador (.A) al ingresar a la rutina.
Esta ubicación se utiliza para determinar qué operación realizar.

148 $ 94
Bandera C3PO : Bus serial - El carácter de salida se almacenó en búfer

Esta ubicación es utilizada por las rutinas de salida en serie para indicar que un
carácter se ha colocado en el búfer de salida y está esperando ser
enviado.

149 $ 95 BSOUR
Carácter en búfer para bus serie

Este es el carácter en espera de ser enviado. Un 255 ($ FF) indica que


ningún carácter está esperando una salida en serie.
www.unusedino.de/ec64/technical/project64/mapping_c64.html 18/126
25/9/2020 Mapping The C64

150 $ 96 SYNO
Cassette Block Synchronization Number

151 $ 97 XSAV
Área de almacenamiento de registro .X temporal

Esta área de almacenamiento de registro .X es utilizada por las rutinas que obtienen y colocan un
carácter ASCII.

152 $ 98 LDTND
Número de archivos de E / S abiertos / índice hasta el final de las tablas de archivos

El número de archivos de E / S abiertos actualmente se almacena aquí. El


número máximo que se puede abrir a la vez es diez. El número almacenado aquí se
usa como índice al final de las tablas que contienen los números de archivo, números de
dispositivo y números de dirección secundaria (consulte las ubicaciones 601-631
($ 259- $ 277) para obtener más información sobre estas tablas).

CLOSE disminuye este número y elimina entradas de las tablas


mencionadas anteriormente, mientras que OPEN lo aumenta y agrega la
información apropiada al final de las tablas. La rutina CLALL de Kernal cierra
todos los archivos estableciendo este número en 0, lo que efectivamente vacía la
tabla.

153 $ 99 DFLTN
Dispositivo de entrada predeterminado (establecido en 0 para teclado)

El valor predeterminado de esta ubicación es 0, que designa el teclado


como el dispositivo de entrada actual. Ese valor se puede cambiar mediante la
rutina de Kernal CHKIN (61966, $ F20E), que usa esta ubicación para almacenar el
número de dispositivo del dispositivo cuyo archivo define como un canal de entrada.

BASIC llama a CHKIN siempre que se ejecuta el comando INPUT # o GET #, pero
borra el canal después de que la operación de entrada se ha completado.

154 $ 9A DFLTO Dispositivo de


salida predeterminado (CMD) (establecido en 3 para la pantalla)

El valor predeterminado de esta ubicación es 3, que designa la pantalla


como dispositivo de salida actual. Ese valor se puede cambiar mediante la
rutina Kernal CHKOUT (62032, $ F250), que usa esta ubicación para almacenar el
número de dispositivo del dispositivo cuyo archivo define como un
canal de salida .

BASIC llama a CHKOUT siempre que se ejecuta el comando PRINT # o CMD, pero
borra el canal después de que se ha completado la operación PRINT #.

155 $ 9B PRTY
Paridad de caracteres de cinta

Esta ubicación se utiliza para ayudar a detectar cuándo se


han perdido bits de información durante la transmisión de datos de cinta.

156 $ 9C DPSW
Indicador: Byte de cinta recibido

Esta ubicación se utiliza como indicador para indicar si un byte completo de


se han recibido datos de la cinta o si sólo se han
recibido parcialmente .

157 $ 9D MSGFLG
Indicador: Control de mensajes de Kernal

Este indicador lo establece la rutina de Kernal SETMSG (65048, $ FE18), y


controla si
se mostrarán o no mensajes de error de Kernal o mensajes de control .

Un valor de 192 ($ C0) aquí significa que


se mostrarán tanto el error Kernal como los mensajes de control . Normalmente, esto nunca ocurrirá cuando se usa
BASIC, que prefiere sus propios mensajes de error de texto plano sobre el
ERROR de E / S (número) superficial del Kernal.
Sin embargo, los mensajes de error de Kernal pueden utilizarse cuando está GUARDANDO o CARGANDO con un
monitor de lenguaje de máquina .

Un 128 ($ 80) significa que solo se mostrarán los mensajes de control. Tal
será el caso cuando esté en el modo directo o inmediato BÁSICO.
Estos mensajes incluyen BUSCANDO, GUARDANDO, ENCONTRADO, etc.

Un valor de 64 significa que los mensajes de error de Kernal solo están activados. Un 0 aquí
suprime la visualización de todos los mensajes de Kernal. Este es el valor que se
coloca aquí cuando BASIC ingresa al programa o al modo RUN.

158 $ 9E PTR1
Tape Pass 1 Error Log Index

Esta ubicación se utiliza para configurar un registro de errores de bytes en los que
se producen errores de paridad de transmisión la primera vez que se
recibe el bloque (cada bloque de cinta se envía dos veces para minimizar la pérdida de datos por
error de transmisión ).

159 $ 9F PTR2
Tape Pass 2 Error Log Correction Index

Esta ubicación se utiliza para corregir bytes de datos de cinta que se


transmitieron incorrectamente en la primera pasada.

160-162 $ A0- $ A2 TIME


www.unusedino.de/ec64/technical/project64/mapping_c64.html 19/126
25/9/2020 Mapping The C64
Software Jiffy Clock

Estas tres ubicaciones se actualizan 60 veces por segundo y sirven como un


reloj de software que cuenta el número de jiffies (sexagésimas de
segundo) que han transcurrido desde que se encendió la computadora.

El valor de la ubicación 162 ($ A2) aumenta cada jiffy (0,1667


segundos), 161 ($ A1) se actualiza cada 256 jiffies (4.2267 segundos) y
160 ($ A0) cambia cada 65536 jiffies (o cada 18.2044 minutos).
Después de 24 horas, estas ubicaciones se vuelven a establecer en 0.

El reloj jiffy es utilizado por las variables reservadas BÁSICAS TI y TI $.


Estas no son variables ordinarias que se almacenan en el
área de variables de RAM , pero son funciones que llaman a las rutinas Kernal RDTIM (63197,
$ F6DD) y SETTIM (63204, $ F6E4). La asignación del valor de TI o TI $
a otra variable lee estas ubicaciones, mientras que la asignación de un
valor dado a TI $ altera estas ubicaciones.

Para ilustrar la relación entre estas ubicaciones y TI $, pruebe


el siguiente programa. El programa establece el jiffy clock en 23 horas y
50 minutos. Después de que el programa se haya ejecutado durante un minuto, todas
estas ubicaciones se restablecerán a 0.

100 TI $ = "235900"
110 PRINT TI $, PEEK (160), PEEK (161), PEEK (162)
120 GOTO 110

Dado que la actualización se realiza mediante la interrupción IRQ que lee el teclado,
cualquier cosa que afecte la operación de esa rutina de interrupción
también interferirá con este reloj. Un ejemplo típico son las
operaciones de E / S de cinta , que roban el vector IRQ para su propio uso y lo restauran
después. Obviamente, las rutinas de usuario que redirigen la IRQ y
no la devuelven a la rutina normal también alterarán el
funcionamiento del reloj del software .

163-164 $ A3- $ A4
Área de almacenamiento temporal de datos

Estas ubicaciones son utilizadas temporalmente por las


rutinas de E / S de cinta y serie .

165 $ A5 CNTDN
Cuenta regresiva de caracteres de sincronización de casete

Se utiliza para hacer una cuenta regresiva del número de caracteres de sincronización que se
envían antes de los datos reales en un bloque de cinta.

166 $ A6 BUFPNT
Recuento de caracteres en el búfer de E / S de cinta

Esta ubicación se utiliza para contar el número de bytes que se han leído
o escrito en el búfer de cinta. Dado que en una escritura en cinta, no se
envían datos hasta que el búfer de 192 bytes está lleno, puede forzar la salida del
búfer con la declaración POKE 166,191.

167 $ A7 INBIT
Bits de entrada RS-232 / Cassette Área de almacenamiento temporal

Esta ubicación se utiliza para almacenar temporalmente cada bit de datos en serie
que se recibe, así como para tareas diversas mediante E / S de cinta.

168 $ A8 BITCI
Recuento de bits de entrada RS-232 / Almacenamiento temporal de cassettes

Esta ubicación se utiliza para contar el número de bits de datos en serie que
se han recibido. Esto es necesario para que las rutinas en serie
sepan cuándo se ha recibido una palabra completa. También se utiliza como
indicador de error durante la carga de cintas.

169 $ A9 RINONE
RS-232 Indicador: Comprobar bit de inicio

Este indicador se utiliza cuando se comprueba un bit de inicio. Un 144 ($ 90) aquí
indica que no se recibió ningún bit de inicio, mientras que un 0 significa que
se recibió un bit de inicio .

170 $ AA RIDATA
RS-232 Entrada Byte Buffer / Casete Almacenamiento temporal Las

rutinas seriales utilizan esta área para reensamblar los bits recibidos en un
byte que se almacenará en el puntero del búfer de recepción por 247
($ F7). Las rutinas de cinta utilizan esto como una bandera para ayudar a determinar si un
carácter recibido debe tratarse como datos o como un
carácter de sincronización .

171 $ AB RIPRTY
RS-232 Paridad de entrada / Contador de líder de cassete

Esta ubicación se utiliza para ayudar a detectar si se perdieron datos durante la


transmisión RS-232 o si se completó un líder de cinta.

172-173 $ AC- $ AD SAL


Puntero a la dirección de inicio de una carga / desplazamiento de pantalla

El puntero al inicio del área de RAM que se va a GUARDAR o CARGAR en 193


($ C1) se copia aquí. Este puntero se utiliza como una versión de trabajo, para
aumentará a medida que se reciben o transmiten los datos. Al final de
la operación, aquí se restaura el valor inicial. Las
www.unusedino.de/ec64/technical/project64/mapping_c64.html 20/126
25/9/2020 Mapping The C64
rutinas de gestión de pantalla lo utilizan temporalmente como un puntero de trabajo.

174-175 $ AE- $ AF EAL


Puntero a la dirección final de la carga (fin del programa)

Esta ubicación la establece la rutina Kernal SAVE para que apunte a la


dirección final para SAVE, LOAD o VERIFY.

176-177 $ B0- $ B1 CMP0 La


ubicación de
temporización de la cinta
176 ($ B0) se utiliza para determinar el valor de la
constante de temporización ajustable en 146 ($ 92). La ubicación 199 también se utiliza en la sincronización
de las lecturas de cinta.

178-179 $ B2- $ B3
Puntero TAPE1 : Inicio del búfer de cinta

Al encender, este puntero se establece en la dirección del búfer del casete


(828, $ 33C). Este puntero debe contener una dirección mayor o
igual a 512 ($ 200), o se enviará un error de NÚMERO DE DISPOSITIVO ILEGAL
cuando se intente la E / S de cinta.

180 $ B4 BITTS
Recuento de bits de salida RS-232 / Almacenamiento temporal en casete Las

rutinas RS-232 utilizan esto para contar el número de bits transmitidos y


para la paridad y la manipulación de bits de parada. Las rutinas de carga de cinta usan esta
ubicación para marcar cuando están listas para recibir bytes de datos.

181 $ B5 NXTBIT
RS-232 Próximo bit para enviar / Cinta EOT Flag

Esta ubicación es utilizada por las rutinas RS-232 para retener el siguiente bit
ser enviado, y por las rutinas de cinta para indicar qué parte de un bloque
está leyendo actualmente la rutina de lectura.

182 $ B6 RODATA
RS-232 Búfer de bytes de salida Las

rutinas RS-232 usan esta área para desensamblar cada byte que se enviará desde
el búfer de transmisión al que apunta 249 ($ F9).

183 $ B7 FNLEN
Longitud del nombre de archivo actual

Esta ubicación contiene el número de caracteres del nombre de archivo actual.


Los nombres de archivo de disco pueden tener de 1 a 16 caracteres, mientras que los nombres de archivo de cinta
varían de 0 a 187 caracteres de longitud.

Si el nombre de la cinta tiene más de 16 caracteres, el exceso será


truncado por los mensajes BUSCANDO y ENCONTRADO, pero seguirá siendo
presente en la cinta. Esto significa que los programas en lenguaje de máquina destinados
a ejecutarse en la memoria intermedia del casete pueden guardarse como nombres de archivo de cinta.

Siempre se hace referencia a un archivo de disco como un nombre, ya sea completo o genérico
(que contiene los caracteres comodín * o?). Esta ubicación
siempre será mayor que 0 si el archivo actual es un archivo de disco. Las
operaciones de cinta LOAD, SAVE y VERIFY no requieren que se
especifique un nombre y, por lo tanto, esta ubicación puede contener un 0. Si este es
el caso, el contenido del puntero al nombre de archivo en 187 será
irrelevante.

Un comando RS-232 OPEN puede especificar un nombre de archivo de hasta cuatro


caracteres. Estos caracteres se copian en las ubicaciones 659-662
($ 293- $ 296) y determine la velocidad en baudios, la longitud de la palabra y la paridad.

184 $ B8 LA
Número de archivo lógico actual

Esta ubicación contiene el número de archivo lógico del dispositivo que se


está utilizando actualmente . Se pueden
abrir un máximo de cinco archivos de disco y diez archivos en total a la vez.

Los números de archivo van de 1 a 255 (se usa un 0 para indicar los
valores predeterminados del sistema ). Al imprimir en un dispositivo con un número de archivo superior a
127, se enviará un carácter de salto de línea ASCII después de cada
retorno de carro , lo cual es útil para dispositivos como impresoras en serie que requieren
avances de línea además de los retornos de carro.

The BASIC OPEN command calls the Kernal OPEN routine, which sets the
value of this location. In the BASIC statement OPEN 4,8,15, the
logical file number corresponds to the first parameter 4.

185 $B9 SA
Current Secondary Address

This location holds the secondary address of the device currently


being used. The range of valid secondary address numbers is 0 through
31 for serial devices, and 0 through 127 for other devices.

Secondary device numbers mean something different to each device that


they are used with. The keyboard and screen devices ignore the
secondary address completely. But any device which can have more than
un archivo abierto al mismo tiempo, como la unidad de disco, distingue
entre estos archivos utilizando la dirección secundaria al abrir un
archivo de disco . Los números de dirección secundaria 0, 1 y 15-31 tienen un
significado especial para la unidad de disco y, por lo tanto, los números de dispositivo 2-14 solo
www.unusedino.de/ec64/technical/project64/mapping_c64.html 21/126
25/9/2020 Mapping The C64
deben usarse como direcciones secundarias al abrir un archivo de disco.

ABRIR un archivo de disco con una dirección secundaria de 15 permite al usuario


comunicarse con el sistema operativo de disco a través de ese canal. Un
comando LOAD que especifica una dirección secundaria de 0 (por ejemplo,
LOAD "AT BASIC", 8,0) da como resultado que el programa se cargue no en la
dirección especificada en el archivo como dirección inicial, sino en
la dirección apuntada por el inicio del puntero BASIC (43, $ 2B).

Una CARGA con una dirección secundaria de 1 (por ejemplo, CARGAR "AQUÍ", 8,1)
da como resultado que el contenido del archivo se cargue en la dirección
especificada en el archivo. Un archivo de disco que ha sido CARGADO usando una
dirección secundaria de 1 se puede GUARDAR con éxito de la misma manera
(GUARDAR "DOS 5.1", 8,1).

Las CARGAS y GUARDADAS que no especifican una dirección secundaria tendrán por defecto
una dirección secundaria de 0.

Al ABRIR un archivo de grabadora de Datasette, una dirección secundaria de 0


significa que se leerá el archivo, mientras que una dirección secundaria de 1
significa que el archivo se leerá. ser escrito a. Se puede agregar un valor de 2
para indicar que también se debe escribir un marcador de fin de cinta.
Este marcador le dice al Datasette que no busque más
archivos en la cinta, aunque se pueden escribir más archivos en la cinta si se
desea.

Al igual que con la unidad de disco, los comandos LOAD y SAVE usan
direcciones secundarias de 0 y 1 respectivamente para indicar si la operación
debe ser reubicada o no reubicada.

Cuando se abre la impresora 1515 o 1525 con una dirección secundaria de 7,


se utiliza el juego de caracteres en mayúsculas / minúsculas. Si está abierto con
una dirección secundaria de 0, o sin una dirección secundaria,
se utilizará el juego de caracteres gráficos / mayúsculas.

186 $ BA FA
Número de dispositivo actual

Esta ubicación contiene el número del dispositivo que se está


usado. Las asignaciones de números de dispositivo son las siguientes:

0 = Teclado
1 = Grabadora
de casetes de datos 2 = RS-232 / Puerto de usuario
3 = Pantalla
4-5 = Impresora
8-11 = Disco

187-188 $ BB- $ BC FNADR


Puntero: Nombre de archivo actual

Esta ubicación sostiene un puntero a la dirección del nombre de archivo actual.


Si una operación que ABRE un archivo de cinta no especifica un nombre de archivo,
este puntero no se utiliza.

Cuando un nombre de archivo de disco contiene un carácter de espacio desplazado, el resto


del nombre aparecerá fuera de las comillas en el directorio y puede
usarse para comentarios. Por ejemplo, si SAVE "ML [
espacio cambiado ] SYS828", la entrada del directorio leerá "ML" SYS 828. Puede
haga referencia al programa ya sea por la parte del nombre que aparece
entre comillas o por el nombre completo, incluido el espacio desplazado.
Sin embargo, un
programa que aparezca más adelante en el directorio como "ML" SYS 900 no se encontrará solo por referencia a "ML".

Se puede utilizar un nombre de archivo de hasta cuatro caracteres al abrir el


dispositivo RS-232. Estos cuatro caracteres se copiarán en 659-662
($ 293- $ 296), donde se utilizan para controlar parámetros como la
velocidad en baudios , la paridad y la longitud de la palabra.

189 $ BD ROPRTY
Paridad de salida RS-232 / Almacenamiento temporal en casete

Esta ubicación es utilizada por las rutinas RS-232 como un


byte de trabajo de paridad de salida y por la cinta como almacenamiento temporal para el carácter actual
siendo leído o enviado.

190 $ BE FSBLK
Recuento de bloques de lectura / escritura de casete

Utilizado por las rutinas de cinta para contar el número de copias de un


bloque de datos que quedan por leer o escribir.

191 $ BF MYCH
Búfer de bytes de entrada de cinta

Esto es utilizado por las rutinas de cinta como un área de trabajo en la que se
ensamblan los caracteres entrantes .

192 $ C0 Enclavamiento del


motor de la cinta CAS1

Esta ubicación es mantenida por la rutina de interrupción IRQ que escanea


el teclado. Siempre que se presiona un botón en la grabadora,
se verifica esta ubicación. Si contiene un 0, el motor se enciende
configurando el Bit 5 de la ubicación 1 en 0. Cuando se suelta el botón, el
motor de la cinta se apaga y esta ubicación se establece en 0.

Dado que la rutina de interrupción se ejecuta 60 veces por segundo,


www.unusedino.de/ec64/technical/project64/mapping_c64.html 22/126
25/9/2020 Mapping The C64
no podrá mantener la bit del motor configurado para mantener el motor encendido si no
se presiona ningún botón. Del mismo modo, si intenta apagar el motor cuando
se presiona un botón y esta ubicación se establece en 0, la rutina de interrupción lo
volverá a encender.

Para controlar el motor a través del software, debe establecer esta ubicación en un
valor distinto de cero después de presionar uno de los botones del registrador
.

193-194 $ C1- $ C2 STAL


I / O Start Address

Esta ubicación apunta a la dirección inicial del área en RAM que


se está cargando o guardando actualmente. Para E / S de cinta, apuntará al
búfer del casete, y el resto de los datos se CARGAN o GUARDAN
directamente hacia o desde la RAM. Esta ubicación apunta a la
dirección inicial del área de RAM que se utilizará para los bloques de datos que vienen
después del encabezado inicial.

197 $ C5 Coordenada de
matriz LSTX de la última tecla presionada, 64 = Ninguna presionada

Durante cada entrada normal de IRQ, esta ubicación se establece con el valor
de la última pulsación de tecla, que se utilizará en la eliminación de rebotes del teclado. El
sistema operativo puede verificar si la pulsación de tecla actual es la misma que la
última y no repetirá el carácter si lo es.

El valor devuelto aquí se basa en los valores de la matriz del teclado como se
establece en la explicación de la ubicación 56320 ($ DC00). Los valores
devueltos por cada tecla presionada se muestran en la entrada de la ubicación 203
($ CB).

198 $ C6 NDX
Número de caracteres en el búfer del teclado (cola)

El valor aquí indica el número de caracteres que esperan en el


búfer del teclado en 631 ($ 277). El número máximo de caracteres en
el búfer del teclado en cualquier momento está determinado por el valor en la
ubicación 649 ($ 289), que por defecto es 10.

Si INPUT o GET se ejecuta mientras ya hay caracteres en el


búfer, esos caracteres se leerán como parte del flujo de datos. Tú
puede evitar esto colocando un 0 en esta ubicación antes de esas
operaciones, lo que siempre hará que se
ignore cualquier carácter en el búfer . Esta técnica puede ser útil cuando se usa el joystick en el
puerto del controlador n. ° 1, lo que a veces provoca que se
registren pulsaciones de teclas falsas , lo que coloca caracteres no deseados en el búfer del teclado.

Esta ubicación no solo es útil para sacar caracteres no deseados del


búfer del teclado, sino que también se puede usar para poner los caracteres deseados
en el búfer y, por lo tanto, programar el búfer del teclado. Esta
técnica (teclado dinámico) le permite simular la entrada del teclado en
modo directo desde un programa.

La técnica del teclado dinámico es extremadamente útil, ya que


le permite agregar, eliminar o modificar líneas de programa mientras el programa se
está ejecutando. El esquema básico es introducir los valores de los caracteres PETASCII
que desea imprimir (incluidos los caracteres de control del cursor y
los retornos de carro) en el búfer. Luego, cuando se
ejecuta una instrucción END , los caracteres en el búfer se imprimirán y se ingresarán mediante
el retorno de carro.

Esta técnica puede ayudar con el problema de intentar utilizar la


separación de datos y los caracteres de terminación con declaraciones INPUT. Si
intenta INPUT una cadena que tiene una coma o dos puntos, INPUT leerá
solo hasta ese carácter y emitirá un mensaje de error EXTRA IGNORED.
Puede evitar esto ingresando la cadena de entrada entre comillas, pero esto
coloca en el usuario la molestia de recordar las comillas. Una
solución es utilizar las declaraciones:

POKE 198,3: POKE 631,34: POKE 632,34: POKE 633,20

antes de la entrada. Esto forzará dos comillas y una eliminación en


el búfer. La primera comilla permite que la coma o los dos puntos sean
INPUT, la segunda se usa para sacar al editor del modo de comillas y la
eliminación elimina la segunda comilla.

Para obtener información más específica y ejemplos de programación, consulte la


descripción de la ubicación 631 ($ 277), el búfer del teclado.

199 $ C7
Bandera RVS : ¿Imprimir caracteres inversos? 0 = No

Cuando los caracteres [CTRL] [RVS-ON] son de impresora (CHR $ (18)), esta bandera
se establece en 18 ($ 12), y las rutinas de impresión agregarán 128 ($ 80) al
código de pantalla de cada carácter que se imprima, de modo que el carácter
aparecerá en la pantalla con sus colores invertidos.

PULSAR esta ubicación directamente con un número distinto de cero logrará los
mismos resultados. Sin embargo, debe recordar que el contenido de esta
ubicación se devuelve a 0 no solo al ingresar un carácter [CTRL] [RVS-OFF]
(CHR $ (146)), sino también en cada retorno de carro. Cuando esto
sucede, los caracteres impresos a partir de entonces aparecen con la
combinación normal de colores.

200 $ C8
Puntero INDX : Fin de la línea lógica para la entrada

www.unusedino.de/ec64/technical/project64/mapping_c64.html 23/126
25/9/2020 Mapping The C64
Este puntero indica el número de columna del último no en blanco
carácter en la línea lógica que se va a introducir. Dado que una
línea lógica puede tener hasta 80 caracteres, este número puede oscilar entre 0 y 79.

201-202 $ C9- $ CA LXSP


Cursor X, Y Posición al inicio de la entrada

Estas ubicaciones realizan un seguimiento de la línea lógica en la que se encuentra el cursor


y su posición de columna en esa línea lógica (en línea, formato de columna).

Cada línea lógica puede contener una o dos líneas físicas de 40 columnas.
Por lo tanto, puede haber hasta 25 líneas lógicas, o tan solo 13 al
mismo tiempo. Por lo tanto, el número de línea lógica puede estar entre 1 y
25. Dependiendo de la longitud de la línea lógica, la columna del cursor
puede ser de 1 a 40 o de 1 a 80.

Para obtener una explicación más detallada de las líneas lógicas, consulte la descripción
del enlace de línea de pantalla talbe, 217 ($ D9).

203 $ CB
Matriz SFDX Coordenada de tecla actual presionada

La rutina de interrupción de exploración de teclas usa esta ubicación para indicar qué tecla
se está presionando actualmente. El valor aquí se usa luego como un índice
en la tabla de teclado apropiada para determinar qué carácter
imprimir cuando se presiona una tecla.

La correspondencia entre la tecla presionada y el número almacenado aquí


es la siguiente:

0 = INST / DEL 34 = J
1 = RETURN 35 = 0
2 = CRSR RIGHT 36 = M
3 = F7 37 = K
4 = F1 38 = O
5 = F3 39 = N
6 = F5 40 = +
7 = CRSR ABAJO 41 = P
8 = 3 42 = L
9 = W 43 = -
10 = A 44 =.
11 = 4 45 =:
12 = Z 46 = @
13 = S 47 =,
14 = E 48 = LIRA (SIGNO DE LA LIBRA BRITÁNICA)
15 = NO SE UTILIZA 49 = *
(SERÍA CAMBIO IZQUIERDO) 50 =;
16 = 5 51 = CLR / HOME
17 = R 52 = NO SE UTILIZA
18 = D (SERÍA EL CAMBIO CORRECTO)
19 = 6 53 = =
20 = C 54 = FLECHA ARRIBA
21 = F (SIGNO DE EXPONENTACIÓN)
22 = T 55 = /
23 = X 56 = 1
24 = 7 57 = FLECHA IZQUIERDA
25 = Y 58 = NO SE UTILIZA
26 = G ( SERÍA CTRL)
27 = 8 59 = 2
28 = B 60 = BARRA ESPACIADORA
29 = H 61 = NO SE UTILIZA
30 = U (SERÍA EL LOGOTIPO DE COMMODORE)
31 = V 62 = Q
32 = 9 63 = RUN / STOP
33 = I 64 = NO HAY TECLA PULSADA

La tecla RESTORE no se tiene en cuenta porque no forma parte de la


matriz del teclado normal. En cambio, está conectado directamente a la
línea NMI del microprocesador y provoca una interrupción NMI cada vez que se
presiona.

204 $ CC BLNSW
Cursor Blink Enable: 0 = Flash Cursor

Cuando este indicador se establece en un valor distinto de cero, le indica a la rutina


que normalmente parpadea el cursor que no lo haga. El parpadeo del cursor se
apaga cuando hay caracteres en el búfer del teclado o cuando
el programa se está ejecutando.

Puede usar esta ubicación para encender el cursor durante un programa (para
una serie de operaciones GET, por ejemplo, para mostrarle al usuario que la entrada
se espera) mediante el uso de la declaración POKE 204,0.

205 $ CD BLNCT
Temporizador: cuenta regresiva para hacer

parpadear el cursor La rutina de interrupción que hace parpadear el cursor utiliza esta ubicación para
indicar cuándo es el momento de parpadear. Primero se pone aquí el número 20, y
cada jiffy (1/60 de segundo) el valor aquí se reduce en uno, hasta que
llega a cero. Luego, el cursor parpadea, el número 20 se vuelve a colocar
aquí y el ciclo comienza de nuevo. Por tanto, en
circunstancias normales , el cursor parpadea tres veces por segundo.

206 $ CE GDBLN
Carácter bajo el cursor

El cursor se forma imprimiendo el inverso del carácter que


ocupa la posición del cursor. Si ese carácter es la letra A, por
www.unusedino.de/ec64/technical/project64/mapping_c64.html 24/126
25/9/2020 Mapping The C64
ejemplo, el cursor intermitente simplemente alterna entre imprimir una A
y una A inversa. Esta ubicación realiza un seguimiento del código
de pantalla normal del carácter que se encuentra en la posición del cursor, de modo que se
puede restaurar cuando el cursor se mueve.

207 $ CF BLNON
Bandera: ¿Estaba activado o desactivado Last Curson Blink?

Esta ubicación realiza un seguimiento de si, durante el parpadeo actual del cursor,
el carácter debajo del cursor se invirtió o se restableció a la
normalidad. Esta ubicación contendrá un 0 si el carácter se invierte
y un 1 si el carácter se restaura a su estado no invertido .

208 $ D0 CRSW
Bandera: Entrada desde el teclado o la pantalla

La rutina Kernal CHRIN (61783, $ F157) utiliza esta bandera para


indicar si la entrada está disponible desde la pantalla (3) o si se
debe obtener una nueva línea desde el teclado (0).

209-210 $ D1- $ D2 PNT


Puntero a la dirección de la línea de la pantalla actual

Esta ubicación apunta a la dirección en la RAM de la pantalla de la primera columna


de la línea lógica en la que está posicionado el cursor.

211 $ D3 RCNP
cursor en la columna L actual ine

El número contenida aquí es la posición de la columna del cursor dentro de la


línea lógica apuntada por 209 ($ D1). Dado que una lnea lgica puede
contener hasta dos líneas físicas, este valor puede ser de 0 a 79 (el
número aquí es el valor devuelto por la función POS).

212 $ D4 QTSW
Bandera: ¿Editor en modo de cotización? 0 = No

Un valor distinto de cero en esta ubicación indica que el editor está en


modo de cotización . El modo de cotización se alterna cada vez que escribe una comilla
en una línea determinada: la primera comilla la activa, la segunda
la desactiva, la tercera la vuelve a activar, etc.

Si el editor está en este modo cuando


se ingresa un carácter de control del cursor u otro carácter no imprimible, aparecerá un equivalente impreso en
la pantalla en lugar del movimiento del cursor u otra operación de control
teniendo lugar. En cambio, esa acción se pospone hasta que la cadena se
envía a la cadena mediante una instrucción PRINT, momento en el que
se llevará a cabo el movimiento del cursor u otra operación de control.

La excepción a esta regla es la tecla DELETE, que funcionará


normalmente dentro del modo de cotización. La única forma de imprimir un carácter que
sea equivalente a la tecla BORRAR es ingresando al modo de inserción (vea la
ubicación 216 ($ D8)). Se puede salir del modo de cotización imprimiendo una
cotización de cierre o presionando las teclas RETURN o SHIFT-RETURN.

A veces, sería útil poder salir del modo de cotización o del


modo de inserción sin saltar a una nueva línea. El
programa de lenguaje de máquina a continuación se conecta a la rutina de interrupción de la exploración de teclas y le permite
para escapar del modo de cotización cambiando esta bandera a 0 cuando presiona la
tecla f1 :

10 PARA I = 850 A I + 41: LEER A: POKE I, A: SIGUIENTE


20 PRINTCHR $ (147) "PRESIONE LA TECLA F1 PARA SALIR DEL MODO DE PRESUPUESTO "
30 PRINT" PARA REINICIAR DESPUÉS DE RESTAURAR SOLAMENTE, SYS 850 ": SYS850: NEW
40 DATA 173, 143, 2, 141, 46, 3, 173, 144, 2, 141
50 DATA 47, 3, 120, 169, 107, 141, 143, 2, 169, 3
60 DATOS 141, 144, 2, 88, 96, 165, 203, 201, 4, 208
70 DATOS 8, 169, 0, 133, 212, 133, 216, 133, 199, 108, 46,

3213 $ D5 LNMX
Longitud máxima de la línea de pantalla física

El editor de línea utiliza esta ubicación cuando se


llega al final de una línea para determinar si se puede agregar otra línea física a la línea
línea lógica actual, o si se debe iniciar una nueva línea lógica.

214 $ D6 TBLX
Cursor actual Número de línea física

Esta ubicación contiene la posición actual de la línea de pantalla física


del cursor (0-24). Se puede usar de alguna manera para mover el cursor
verticalmente, pinchando la línea de la pantalla de destino (1-25) menos 1 aquí,
seguido de un comando PRINT. Por ejemplo,

POKE 214,9: PRINT: PRINT "WE'RE ON LINE ELEVEN"

imprime el mensaje en la línea 11. La primera instrucción PRINT permite al


sistema actualizar las otras variables del editor de pantalla para que
también muestren la nueva línea. El cursor también se puede configurar o leer usando la
rutina Kernal PLOT (58634, $ E50A) como se explica en la entrada de
ubicaciones 780-783 ($ 30C- $ 30F).

215 $ D7
Área de almacenamiento temporal para el valor ASCII del último carácter impreso

El valor ASCII del último carácter impreso en la pantalla se mantiene


aquí temporalmente.

www.unusedino.de/ec64/technical/project64/mapping_c64.html 25/126
25/9/2020 Mapping The C64
216 $ D8
Bandera INSRT : modo de inserción (cualquier número mayor que 0 es el número de inserciones)

Cuando se presiona la tecla INST, el editor de pantalla desplaza la línea hacia la


derecha, asigna otra línea física a la línea lógica si es
necesario (y posible ), actualiza la longitud de la línea de la pantalla en 213 ($ D5)
y ajusta la tabla de enlace de la línea de la pantalla en 217 ($ D9). Esta ubicación se
utiliza para realizar un seguimiento del número de espacios que se han abierto de
esta manera.

Hasta que se llenen los espacios que se han abierto, el editor actúa
como si estuviera en modo de cotización (consulte la ubicación 212 ($ D4), la bandera del modo de cotización).
Esto significa que los caracteres de control del cursor que normalmente
no se imprimen dejarán un equivalente impreso en la pantalla cuando se
ingresen, en lugar de tener su efecto normal en el movimiento del cursor,
etc. La única diferencia entre el modo insertar y el modo de cotización es que la
tecla BORRAR dejará un equivalente en el modo de inserción, mientras que la
tecla INST insertará espacios de forma normal.

217-242 $ D9- $ F2 LDTB1


Tabla de enlace de línea de pantalla / Editor Almacenamiento temporal

Esta tabla contiene 25 entradas, una para cada fila de la pantalla


monitor. Cada entrada tiene dos funciones. Los bits 0-3 indican en cuál de
las cuatro páginas de la memoria de pantalla se encuentra el primer byte de memoria para esa fila
. Esto se utiliza para calcular el puntero a la
dirección inicial de una línea de pantalla en 209 ($ D1).

Si bien los PET anteriores usaban una tabla para los bytes bajos de las filas de la pantalla y
otra para los bytes altos, esto no es posible en el 64, donde
la memoria de la pantalla no está fija en ningún lugar. Por lo tanto, el
sistema operativo usa una tabla de bytes bajos en 60656 ($ ECF0), pero calcula el
byte alto agregando el valor de la página de inicio de la memoria de pantalla que se encuentra
en 648 ($ 288) a la página de desplazamiento que se encuentra aquí.

La otra función de esta tabla es establecer la composición de


líneas lógicas en la pantalla. Si bien cada línea de la pantalla tiene solo 40 caracteres
, BASIC permite la entrada de líneas de programa que contienen hasta 80
caracteres. Por lo tanto, se debe utilizar algún método para determinar qué
pares de líneas físicas están vinculadas en una línea lógica más larga, de modo que
esta línea lógica más larga pueda editarse como una unidad.

El bit alto de cada byte aquí es usado como un indicador por el editor de pantalla.
Ese bit se establece (dejando el valor del byte por encima de 128 ($ 80)) cuando una
línea es la primera o única línea física en una línea lógica. El
bit alto se restablece a 0 solo cuando una línea es la segunda mitad de una
línea lógica .

243-244 $ F3- $ F4 USER


Puntero a la dirección de la ubicación actual de la RAM del color de la pantalla

Este puntero está sincronizado con el puntero a la dirección del


primer byte de la RAM de la pantalla para la línea actual que se mantiene en la ubicación 209
($ D1). Contiene la dirección del primer byte de RAM de color para la
línea de pantalla correspondiente.

245-246 $ F5- $ F6 KEYTAB


Vector: Tabla de decodificación de teclado

KEYTAB apunta a la dirección de la tabla de búsqueda de matriz de teclado que


se está utilizando actualmente. Aunque solo hay 64 teclas en la
matriz del teclado , cada tecla se puede utilizar para imprimir hasta cuatro caracteres diferentes,
dependiendo de si se pulsa sola o en combinación con la
Teclas del logotipo de SHIFT, CTRL o Commodore.

Las tablas apuntadas a esta dirección contienen el valor ASCII de cada una de
las 64 teclas para una de estas posibles combinaciones de pulsaciones de teclas.
Cuando llega el momento de imprimir el carácter, la tabla que se utiliza
determina qué carácter se imprime.

Las direcciones de las cuatro tablas son:

60289 ($ EB81) = mayúsculas / caracteres gráficos predeterminados (sin


cambiar ) 60354 ($ EBC2) = caracteres cambiados
60419 ($ EC03) = caracteres clave del logotipo de Commodore
60536 ($ EC78) = caracteres CTRL

El concepto de las tablas de la matriz del teclado no debe confundirse con


cambiar los juegos de caracteres de mayúsculas / gráficos a
mayúsculas / minúsculas. El primero implica determinar qué personaje debe
colocarse en la memoria de la pantalla, mientras que la última implica determinar
qué tabla de datos de caracteres se utilizará para decodificar la memoria de la pantalla
en puntos individuales para la visualización de caracteres en la pantalla.
Esa base de caracteres está determinada por la ubicación 53272 ($ D018) del
chip VIC-II.

247-248 $ F7- $ F8 RIBUF


Puntero: Búfer de entrada RS-232

Cuando se abre el dispositivo número 2 (el canal RS-232),


se crean dos búferes de 256 bytes cada uno en la parte superior de la memoria. Esta ubicación apunta
a la dirección de la que se utiliza para almacenar caracteres a medida que
se reciben. Un programa BÁSICO siempre debe ABRIR el dispositivo 2 antes de
asignar cualquier variable para evitar las consecuencias de sobrescribir
variables que estaban ubicadas anteriormente en la parte superior de la memoria, ya que BASIC
ejecuta un CLR después de abrir este dispositivo.

249-250 $F9-$FA ROBUF


www.unusedino.de/ec64/technical/project64/mapping_c64.html 26/126
25/9/2020 Mapping The C64
Pointer: RS-232 Output Buffer

This location points to the address of the 256-byte output buffer


which is used for transmitting data to RS-232 devices (device number
2)l

251-254 $FB-$FE FREEZP


Four Free Bytes of Zero Page for User Programs

These locations were specifically set aside for user-written ML


routines that require zero-page addressing. While other zero-page
locations can be used on a noninterference basis, it is guaranteed
that BASIC will not alter these locations.

255 $FF BASZPT


BASIC Temporary Data for Floating Point to ASCII Conversion

Esta ubicación se utiliza para el almacenamiento temporal en el proceso de


conversión de números de punto flotante en caracteres ASCII ..

:::::::::::::
:: Capítulo 2 ::
:: ::
:: :: Página 1
: ::::::::::::

256-511 $ 100- $ 1FF


Área de pila del microprocesador Las

ubicaciones 256-511 están reservadas para la


pila de hardware del microprocesador 6510 . La organización de esta área de almacenamiento temporal a menudo se ha
comparado con la de una pila de bandejas de empujar hacia abajo en una cafetería. El
primer número colocado en la pila va a la parte inferior, y luego
las entradas se colocan encima de él. Luego sacas un número de la
pila y obtienes el último número que se presionó (una
pila de este tipo se llama pila de último en entrar , primero en salir o pila LIFO).

La pila está controlada por uno de los registros del microprocesador llamado
Stack Pointer, que realiza un seguimiento de la última ubicación de la pila utilizada.
El primer número que se coloca en la pila va a la ubicación 511 ($ 1FF), y
las entradas siguientes se acumulan hacia abajo hasta 256 ($ 100). Si se
insertan más de 256 números en la pila, el puntero de pila comenzará a
contar desde 0 nuevamente y se producirá un error de desbordamiento. Del mismo modo,
si intenta sacar más elementos de la pila de los que se han empujado,
resultará un error de subdesbordamiento. La mayoría de las veces, tales errores harán que
el sistema se vuelva loco y nada funcionará hasta que
apague y vuelva a encender.

El sistema utiliza la pila para realizar un seguimiento de las direcciones


de retorno de las subrutinas del lenguaje de máquina e interrumpir las llamadas y para guardar el
contenido de los registros internos. El programador también puede utilizar la pila
para almacenamiento temporal. BASIC y Kernal hacen un uso intensivo
de la pila.

Microsoft BASIC usa parte de la pila para un área de trabajo temporal.


Por lo tanto, la pila se puede dividir en las siguientes subregiones:

256-266 $100-$10A
Work Area for Floating Point to String Conversions

Used in the conversion of numbers to the equivalent ASCII digits, and


in scanning strings.

256-318 $100-$13E BAD


Tape Input Error Log

Each tape block is saved twice consecutively, in order to minimize


loss of data from transmission errors. These 62 bytes serve as
indices of which bytes in the tape block were not received corectly
during the first transmission, so that corrections might be made on
the second pass.

319-511 $13F-$1FF

This area is exclusively for the microprocessor stack. Some BASIC


commands, such as FOR-NEXT loops require many stack entries at a time.
Por lo tanto, BASIC comprueba con frecuencia la pila antes de insertar entradas
encendido, y devuelve un error FUERA DE MEMORIA si una operación da como resultado
menos de 62 bytes de memoria de pila disponible.

Cada instrucción FOR hace que se inserten 18 bytes en la pila, que


salen en el siguiente orden:

Primero viene una constante de un byte de 129 ($ 81). El siguiente es un


puntero de dos bytes a la dirección de la variable sujeto (la X de FOR X = 1 a
10). A esto le sigue la representación
de punto flotante de cinco bytes del valor TO. Finalmente viene el número de línea de dos bytes de la línea
a la que el programa regresa después de un SIGUIENTE, y la dirección de dos bytes del
siguiente carácter para leer en esa línea después de la instrucción FOR.

Cada llamada de GOSUB coloca cinco bytes en la pila. El primer byte para
sale es una constante de un byte de 141 ($ 8D). Los siguientes dos bytes
contienen el número de línea de la instrucción a la que el programa
VOLVERÁ después de que finalice la subrutina. Y los dos bytes finales son un
puntero a la dirección del texto del programa BÁSICO para esa declaración en la
que el programa RETORNA.

www.unusedino.de/ec64/technical/project64/mapping_c64.html 27/126
25/9/2020 Mapping The C64
DEF también deja una entrada de cinco bytes en la pila. Es el mismo
que el descrito para GOSUB, excepto que en lugar de un byte constante de
141, el primer número es un byte ficticio, cuyo valor no tiene
significado.

:::::::::::::::::::::::
:: Capítulo 3 ::
:: ::
:: Páginas 2 y 3 ::
:: ::
:: BASIC y el Kernal ::
:: Almacenamiento de trabajo ::
::::::::::::::::::::::::

Esta área se utiliza para almacenar información importante para el


Sistema Operativo y BÁSICO. Contiene vectores para ciertas rutinas BASIC
así como rutinas Kernal del sistema operativo. Los registros para
E / S serie RS-232 se encuentran aquí. El espacio de búfer se asigna en esta área para
E / S de cinta , entrada de texto BÁSICO y la cola del teclado. Además, hay
una serie de variables y punteros del sistema operativo aquí que el
programador puede utilizar.

512-600 $ 200- $ 258 BUF


Búfer de entrada del editor de líneas BÁSICO

Cuando se encuentra en el modo inmediato BÁSICO y escribe una línea de


caracteres, esos caracteres se almacenan aquí. BÁSICO luego escanea el
cadena de caracteres, convierte el texto al
formato de programa BÁSICO tokenizado y lo almacena o ejecuta la línea, dependiendo de
si comenzó o no con un número de línea.

Esta misma área también se utiliza para almacenar datos que se reciben a través de los
comandos INPUT y GET. Esto explica por qué estos comandos son ilegales
en el modo inmediato: deben usar el mismo espacio de búfer que
requiere la instrucción del modo inmediato.

Es interesante notar que este búfer tiene 89 bytes de longitud. El


editor de pantalla permitirá un máximo de solo 80 caracteres en una
línea de programa , con un byte adicional requerido para un carácter 0, que marca el final
de la línea. Este presumible es un traspaso del VIC, que
permite una longitud de línea de hasta 88 caracteres. Por lo tanto, los últimos ocho bytes de
este búfer normalmente no se utilizan y pueden considerarse
espacio libre para que el programador los utilice como mejor le parezca.

Rango de ubicación: 601-630 ($ 259- $ 276)


Tablas para números de archivo, números de dispositivo y direcciones secundarias

Las tres tablas aquí tienen espacio para diez entradas de un byte, cada una
de las cuales representa un archivo de entrada / salida activo. Cuando se
abre un archivo de E / S , su número de archivo lógico se coloca en la tabla en 601 ($ 259),
el número de dispositivo del dispositivo de E / S se coloca en la tabla en 611
($ 263) y su dirección secundaria se coloca en la mesa en 621 ($ 26D).

La entrada para cualquier archivo de E / S en particular ocupará la misma posición en


cada una de las tres tablas. Es decir, si el número de archivo lógico 2 es la
tercera entrada en la tabla de números de archivo, su dirección secundaria será
la tercera entrada en la tabla de direcciones secundaria y su
número de dispositivo correspondiente ocupará el tercer lugar en la tabla de números de dispositivo.

Cada vez que se ABRE un dispositivo, su información se agrega como la última


entrada en cada tabla y el valor en la ubicación 152 ($ 98) se incrementa
en uno, lo que indica que hay un archivo de E / S activo más. Cuando un
dispositivo está CERRADO, el valor en la ubicación 152 se reduce en uno, y
todas las entradas que ocupan una posición en las tablas que es más alta que
la del dispositivo cerrado se mueven hacia abajo una posición, por lo tanto
eliminando la entrada para ese dispositivo. La rutina CLALL de Kernal
(62255, $ F32F) simplemente pone a cero la ubicación 152, lo que tiene el efecto de
vaciar estas tablas.

601-610 $ 259- $ 262


Tabla kernal LAT de números de archivos lógicos activos

611-620 $ 263- $ 26C


Tabla kernal FAT de números de dispositivo para cada archivo lógico

621-630 $ 26D- $ 276


Tabla kernal SAT de direcciones secundarias para cada archivo lógico

631- 640 $ 277- $ 280 Búfer de


teclado KEYD (cola)

Este búfer, a veces también conocido como cola de teclado, contiene


los valores ASCII de los caracteres ingresados desde el teclado. La
rutina de interrupción que escanea el teclado deposita un carácter aquí
cada vez que se presiona una tecla. Cuando BASIC ve que hay caracteres
esperando, los elimina y los imprime, uno por uno, en el orden en que
fueron ingresados.

Este tipo de búfer se conoce como FIFO, en inglés First In, First Out. El
búfer puede contener hasta diez caracteres, lo que le permite escribir más rápido de lo
que la computadora imprime, sin perderlos. El
número máximo de caracteres que este búfer puede contener a la vez es diez
(según lo determinado por el valor de 649 ($ 289)). Los caracteres ingresados después de que
el búfer esté lleno serán ignorados.

Los comandos GET e INPUT recuperan caracteres de este búfer. Si


uno de estos se ejecuta mientras ya hay personajes esperando en
www.unusedino.de/ec64/technical/project64/mapping_c64.html 28/126
25/9/2020 Mapping The C64
el búfer, esos caracteres se recuperarán como si fueran parte de
los datos que se ingresan. Para evitar que esto suceda, puede borrar
el búfer introduciendo un 0 en la ubicación 198 ($ C6), que contiene el
número de caracteres que están esperando en el búfer.

Una de las técnicas más interesantes y útiles para programar


computadoras Commodore es hacer que un programa simule la entrada directa de
comandos desde el teclado. Este truco de teclado dinámico se logra
introduciendo primero los caracteres PETASCII, generalmente
caracteres de movimiento del cursor y retornos de carro, en el búfer y estableciendo la ubicación
198 ($ C6) para mostrar cuántos caracteres están esperando en el búfer.

A continuación, borra la pantalla e IMPRIME las sentencias que desea que


se ejecuten en la pantalla, colocándolas con cuidado de modo que la
primera sentencia a introducir esté en la cuarta línea de la pantalla.

Luego, coloca el cursor en casa y ejecuta una instrucción END. Esto hace
que se lea el búfer del teclado y se
ejecuten los retornos de carro , ingresando así las líneas impresas como si hubieran sido mecanografiadas en modo
inmediato o directo. El programa puede continuar incluyendo una
instrucción GOTO en la última línea ingresada.

Se pueden lograr muchos efectos interesantes usando este método. A


continuación se incluyen ejemplos de algunos de estos. Por ejemplo, las líneas de programa pueden
ser agregado, modificado o eliminado, mientras el programa se está ejecutando. El
siguiente ejemplo muestra cómo se hace esto:

10 REM ESTA LÍNEA SERÁ ELIMINADA


20 REM SE CREARÁ UNA NUEVA LÍNEA 30
40 IMPRIMIR CHR $ (147): IMPRIMIR: IMPRIMIR
50 IMPRIMIR "80 LISTA": IMPRIMIR "30 REM ESTA LÍNEA FUE AQUÍ ANTES DE "
60 IMPRIMA" 10 ": IMPRIMA" GOTO 80 "CHR $ (19)
70 FOR I = 631 TO 634: POKE I, 13: NEXT: POKE 198,4: END
80 REM ESTA LÍNEA SERÁ REEMPLAZADA

Usted puede usar esta técnica para ingresar sentencias de DATOS numeradas
automáticamente, usando valores en la memoria. Estas declaraciones pasan a formar
parte permanente del programa.

Otra aplicación interesante es tomar líneas de programa ASCII de un


archivo de datos de cinta, o archivo de disco secuencial, y que se ingresen
automáticamente. Esto se puede utilizar para fusionar programas o para
transferir programas entre computadoras con un módem y un
programa de terminal . Para crear el archivo de programa ASCII, utilice CMD para dirigir un
LISTADO al dispositivo deseado de la siguiente manera:

Para cinta: OPEN 1,1,1, "ASCII": CMD 1: LIST


Una vez finalizado el listado: PRINT # 1: CLOSE 1

Para el disco: OPEN 8,8,8, "ASCII, S, W": CMD 8: LIST


Una vez finalizado el listado: PRINT # 8: CLOSE 8

Este archivo se puede cargar usando un módem y el


software de terminal apropiado , ingresado por sí mismo o combinado con otro programa utilizando
el siguiente programa. Asegúrese de guardar este programa antes de ejecutar
él, porque se borrará a sí mismo cuando esté hecho.

60000 OPEN 1,8,8, "ASCII"


60010 POKE 152,1: B = 0: GOSUB 60170
60020 GET # 1, A $: IF A $ = "" THEN60020 60030
IF ST AND 64 THEN 60120
60040 IF A $ = CHR $ (13) AND B = 0THEN60020
60050 IMPRIMA A $ ;: B = 1: SI A $ = CHR $ (34) ENTONCES PULSE 212,0
60060 SI A $ <> CHR $ (13) ENTONCES 60020
60070 IMPRIMA CHR $ (5); "GOTO 60010"; CHR $ (5): PRINT: PRINT: POKE 198,0
60080 PRINT "RETURN = KEEP LINE S = SKIP LINE": B = 0
60090 GET A $: IF A $ = "" ENTONCES 60090
60100 SI A $ = "S" ENTONCES 60010
60110 GOTO 60180
60120 IMPRIMIR "FIN DE ARCHIVO - HIT VOLVER PARA FINALIZAR FUSIÓN"
60130 SI PEEK (197) <>
60160 PRINT "A =" I ": GOTO 60150": GOTO 60180 60170
PRINT CHR $ (147): PRINT: PRINT: RETURN
60180 FOR I = 631TO640: POKEI, 13: NEXT: POKE198,10: PRINTCHR $ (19); : FIN

Si desea fusionar programas adicionales al mismo tiempo, cuando


indique que el archivo ha finalizado, presione la tecla STOP en lugar de
RETURN, ingrese el nombre del nuevo archivo en la línea 60000 y RUN 60000

641-642 $ 281- 282 MEMSTR


Pointer: OS Start of Memory

Cuando se enciende por primera vez, o se realiza un RESET de arranque en frío,


la rutina Kernal RAMTAS (64848, $ FD50) establece esta ubicación para que apunte
a la dirección 2048 ($ 800). Esto indica que esta es la
dirección inicial de la RAM del usuario. BASIC usa esta ubicación para establecer su propio inicio de
puntero de memoria en la ubicación 43 ($ 2B) y, a partir de entonces, usa solo su propio
puntero.

La rutina Kernal MEMBOT (65076, $ FE34) se puede utilizar para leer o configurar
este puntero, o estas ubicaciones pueden ser directamente PEEKed o POKEd desde
BASIC.

643-644 $ 283-284 MEMSIZ


Puntero: OS Fin de la memoria

Cuando se enciende por primera vez, o se realiza un RESET de arranque en frío,


la rutina Kernal RAMTAS (64848, $ FD50) realiza una
www.unusedino.de/ec64/technical/project64/mapping_c64.html 29/126
25/9/2020 Mapping The C64
prueba no destructiva de RAM desde 1024 ($ 400) para arriba, deteniéndose cuando la prueba falla, lo que
indica la presencia de ROM. Esto ocurrirá normalmente en 40960
($ A000), la ubicación de la ROM BÁSICA. La parte superior del puntero de la RAM del usuario
se establece para que apunte a la primera ubicación de la ROM.

Después de que se haya iniciado BASIC, el sistema alterará esta ubicación solo
cuando un canal RS-232 (dispositivo número 2) esté ABIERTO o CERRADO. Como
se requieren 512 bytes de memoria para los
búferes de transmisión y recepción RS-232 , este puntero, así como el final del puntero BASIC en 55
($ 37), se reduce para crear espacio para esos búferes cuando se
abre el dispositivo . CERRAR el dispositivo restablece estos punteros.

La rutina Kernal MEMTOP (65061, $ FE25) puede usarse para leer o configurar
este puntero.

645 $ 285
Indicador TIMOUT : Variable Kernal para IEEE Time-Out

Esta ubicación se usa solo con la tarjeta de interfaz IEEE externa


(que aún no estaba disponible en Commodore en el momento de escribir este artículo).
Para obtener más información, consulte la entrada de la rutina Kernal SETTMO en
65057 ($ FE21).

646 $ 286 COLOR


Color de primer plano actual para texto

El proceso de IMPRIMIR un carácter en la pantalla consiste en


colocar el valor del código de pantalla para el carácter en la memoria de la pantalla y
colocar un valor de color de primer plano en la ubicación correspondiente en
la RAM de color. Siempre que se IMPRIME un carácter, el Sistema Operativo recupera
el valor para ponerlo en la RAM de color desde esta ubicación.

El color de primer plano se puede cambiar de varias formas. Si presiona la tecla


CTRL o el logotipo de Commodore y los números del 1 al 8 al mismo tiempo,
cambiará el valor almacenado aquí y, por lo tanto, el color que se imprime.
IMPRIMIR el carácter equivalente de PETASCII con el comando CHR $ tendrá
el mismo efecto. Pero probablemente el método más fácil es empujar el
valor del color directamente a esta ubicación. La siguiente tabla enumera los
posibles colores que pueden producirse y muestra cómo producirlos
utilizando los tres métodos.

POKE
COLOR # COLOR CHR $ TECLAS A PULSAR
0 Negro 144 CTRL-1
1 Blanco 5 CTRL-2
2 Rojo 28 CTRL-3
3 Cian 159 CTRL-4
4 Morado 156 CTRL-5
5 Verde 30 CTRL-6
6 Azul 31 CTRL- 7
7 Amarillo 158 CTRL-8
8 Naranja 129 Logo-1
9 Marrón 149 Logo-2
10 Rojo Lt 150 Logo-3
11 Gris Oscuro 151 Logo-4
12 Gris Medio 152 Logo-5
13 Verde Lt 153 Logo-6
14 Azul Lt 154 Logo-7
15 Gris Lt 155 Logo-

8647 $ 287 GDCOL


Color del carácter bajo el cursor

Esta ubicación se utiliza para realizar un seguimiento del código de color original del
carácter almacenado en la ubicación actual del cursor. Dado que el
cursor parpadeante usa el color de primer plano actual en 646 ($ 286), el
valor original debe almacenarse aquí para que si el cursor se mueve sin
cambiar ese carácter, su código de color se pueda restaurar a su
valor original.

648 $ 288 HIBASE


Página superior de memoria de pantalla

Esta ubicación contiene el valor utilizado por las rutinas del sistema operativo
que se imprimen en la pantalla como la dirección base para la RAM de la pantalla. La parte superior
de la memoria de la pantalla se puede encontrar multiplicando esta ubicación por 256.
El valor predeterminado para la RAM de la pantalla se establece en el encendido en la ubicación 1024
($ 400) y, por lo tanto, esta ubicación generalmente contiene una

memoria de visualización de pantalla en el Commodore 64. se puede mover para comenzar en cualquier
límite de 1K (ubicación uniformemente divisible por 1024). Esto se hace
manipulando la selección del banco de memoria del chip VIC-II en la ubicación 56576
($ DD00).

Sin embargo, es importante señalar que, si bien cualquier área puede


mostrado, el sistema operativo buscará aquí para averiguar dónde
debe IMPRIMIR caracteres. Por lo tanto, si cambia la ubicación de la pantalla
alterando el contenido de una de las dos direcciones enumeradas anteriormente, el
sistema operativo aún no sabrá dónde IMPRIMIR caracteres a menos
que también cambie esta dirección. El resultado será que los
caracteres ingresados desde el teclado o PRINTed no aparecerán en la
pantalla.

Se pueden encontrar ejemplos de cómo reubicar correctamente la pantalla en las


entradas para la ubicación 53272 ($ D018) y 43 ($ 2B).

Dado que el comando PRINT, en esencia, solo introduce una gran cantidad de valores en la
pantalla y la memoria de color, al cambiar este puntero puede imprimir un
www.unusedino.de/ec64/technical/project64/mapping_c64.html 30/126
25/9/2020 Mapping The C64
cadena de caracteres a ubicaciones de memoria distintas de la RAM de pantalla. Por
ejemplo, puede IMPRIMIR la forma de un sprite en la memoria sin tener que
LEER muchas declaraciones de DATOS. El siguiente programa IMPRIME diferentes
formas de sprites en el área de datos de sprites:

10 SP = 53248: POKESP, 170: POKESP + 1,125: POKESP + 21,1: POKE 2040,13: PRINT CHR $ (147)
20 A $ = "ESTE TEXTO SE IMPRIMIRÁ EN EL ÁREA DE DATOS DE SPRITE SHAPE Y SE MOSTRARÁ "
30 GOSUB 100
40 A $ =" ESTE ES UN TEXTO DIFERENTE PARA IMPRIMIR EN EL ÁREA DE SPRITE SHAPE "
50 GOSUB 100
60 CUENTA = CUENTA + 1: SI CUENTA <15 ENTONCES 20
70 END
100 POKE 648,3: PRINT CHR $ (19); CHR $ (17); SPC $ (24); A $ ;: POKE 648,4: RETURN

Dado que la IMPRESIÓN también cambia la memoria de color, puede cambiar el puntero
para imprimir los caracteres de forma inofensiva en la ROM, mientras cambia una gran cantidad de
RAM de pantalla a la vez, como lo demuestra el siguiente programa:

10 D $ = CHR (94): FOR I = 1 TO 4: D $ = D $ + D $: NEXT


20 PRINT CHR $ (147) ;: FOR I = 1 TO 7: PRINT TAB (10) D $: NEXT: PRINT: PRINT: PRINT: PRINT
30 PRINT TAB (9); CHR $ (5); "HIT CUALQUIER LLAVE PARA PARAR "
40 DIM C (15): FOR I = 0TO14: LEER A: C (I) = A: NEXT: DATA2,8,7,5,6,4,1,2,8,7,5, 6,4,1,2
50 POKE 53281,0: POKE 648,212: FOR J = 0 TO 6: PRINT CHR $ (19);
60 PARA I = J TO J + 6: POKE 646, C (I): PRINT TAB (10) D $: NEXT I, J
70 OBTENER A $: SI A $ = "" ENTONCES 50
80 POKE 648,4: POKE 646,1

649 $ 289 XMAX


Tamaño máximo de búfer de teclado

El valor aquí indica el número máximo de caracteres que


El búfer de teclado a 631 ($ 277) puede contener en cualquier momento. Siempre que
la longitud del búfer actual en la ubicación 198 ($ C6) coincida con el valor
aquí, se ignorarán las pulsaciones de teclas adicionales.

Aunque el tamaño máximo del búfer del teclado suele ser de 10


caracteres, es posible ampliarlo hasta 15 caracteres
cambiando el número aquí. Esto podría hacer que los
punteros del sistema operativo a la parte inferior y superior de la memoria en 641-644 ($ 281- $ 284) se
sobrescriban, pero no debería producirse ningún daño real.

650 $ 28A
Bandera RPTFLAG : ¿Qué teclas se repetirán ?

La bandera en esta ubicación se usa para determinar si continuar


imprimiendo un carácter mientras se mantenga presionada la tecla, o si
espere hasta que suelte la tecla antes de permitir que se imprima de nuevo.
El valor predeterminado aquí es 0, lo que permite que solo se
repitan las teclas de movimiento del cursor, la tecla insertar / eliminar y la barra espaciadora.

POKE en esta ubicación con 128 ($ 80) hará que todas las claves se repitan,
mientras que un valor de 64 ($ 40) impedirá que todas las claves se repitan.

651 $ 28B
Contador KOUNT para cronometrar el retraso entre repeticiones de teclas

Esta ubicación se utiliza como un contador de demoras para determinar cuánto tiempo esperar
mientras se mantiene presionada una tecla hasta la siguiente impresión repetida de esa
tecla.

El valor aquí comienza en 6. Si la ubicación 652 ($ 28C) contiene un 0, el


valor en esta ubicación se cuenta hacia atrás una vez cada 1/60 de segundo, por tanto
mientras se mantiene pulsada la misma tecla. Cuando este contador llega a 0, y si el
indicador de repetición en 650 ($ 28A) permite que la tecla se repita, su
equivalente ASCII se colocará nuevamente en el búfer del teclado. A
continuación, se coloca un valor de 4 en la ubicación 651, lo que permite que se
produzcan repeticiones posteriores a una velocidad de 15 por segundo.

652 $ 28C DELAY


Contador para cronometrar el retraso hasta que comience la repetición de la primera tecla

Esta ubicación se utiliza como un contador de retraso para determinar cuánto tiempo se
debe mantener presionada una tecla antes de que se deba repetir la entrada de esa tecla.

El valor inicial de 16 se cuenta hacia atrás cada 1/60 de segundo, siempre que se
mantenga presionada la misma tecla. Cuando el valor llega a 0, ubicación 651
($ 28B) se cuenta hacia atrás desde 6, y la clave se repite cuando el valor
llega a 0. Por lo tanto, un total de 22/60, o aproximadamente 1/3 de segundo,
pasará antes de la primera repetición de una clave. El valor aquí se
mantendrá en 0 después de la primera repetición, de modo que las
repeticiones de pulsaciones posteriores se produzcan mucho más rápidamente.

653 $ 28D
Bandera SHFLAG : MAYÚS / CTRL / Pulsación de tecla del logotipo

Esta bandera indica cuál de las teclas del logotipo SHIFT, CTRL o Commodore se
está presionando actualmente, si es que hay alguna.

Un valor de 1 significa que se está presionando una de las teclas SHIFT, un


2 muestra que la tecla del logotipo de Commodore está presionada y 4 significa que
se está presionando la tecla CTRL . Si se mantiene presionada más de una tecla, estos valores
será añadido; por ejemplo, un 3 indica que se
mantienen presionados SHIFT y el logotipo .

El valor aquí lo utiliza el sistema operativo para determinar cómo


convertir una pulsación de tecla en un carácter PETASCII. Hay cuatro
tablas diferentes que se utilizan para traducir una de las 64 teclas de la
matriz del teclado en un carácter PETASCII, y la combinación de
www.unusedino.de/ec64/technical/project64/mapping_c64.html 31/126
25/9/2020 Mapping The C64
teclas especiales SHIFT determina cuál de estas tablas se utilizará (consulte la entrada de la
ubicación 245 ($ F5) para obtener más información detalles en las tablas del teclado).

Al presionar las teclas SHIFT y el logotipo de Commodore al mismo tiempo,


el conjunto de caracteres que se está utilizando actualmente entre el conjunto de
mayúsculas / gráficos y el conjunto de minúsculas / mayúsculas (siempre que
la bandera en 657 ($ 291) no se ha configurado para deshabilitar este interruptor).

Esto cambia la apariencia de todos los personajes en la pantalla a la


vez. Sin
embargo, no tiene nada que ver con las tablas de desplazamiento del teclado y no debe confundirse con la impresión de
caracteres SHIFTed , que afecta sólo a un carácter a la vez. Más bien, es
el resultado del cambio del valor de la dirección base de la tabla de datos de puntos de carácter
en 53272 ($ D018). El resultado obtenido puede obtenerse
presionando directamente esa dirección.

654 $ 28E LSTSHF


Último patrón de pulsación de tecla SHIFT / CTRL / Logo

Esta ubicación se usa en combinación con la anterior para eliminar el rebote


las teclas especiales SHIFT. Esto evitará que la combinación SHIFT / logo
cambie los conjuntos de caracteres hacia adelante y hacia atrás durante una sola pulsación
de ambas teclas.

655-656 $ 28F- $ 290 KEYLOG


Rutina de configuración de vector a tabla de teclado

Esta ubicación apunta a la dirección de la rutina del sistema operativo


que realmente determina qué tabla de búsqueda de matriz de teclado se
utilizará.

La rutina mira el valor de la bandera SHIFT en 653 ($ 28D) y,


según el valor que encuentre allí, almacena la dirección de la
tabla correcta para usar en la ubicación 245 ($ F5).

La rutina de exploración del teclado impulsada por interrupciones salta a través de este
vector RAM para llegar a la rutina de configuración de la tabla. Por tanto, es posible
para alterar la dirección contenida en este vector y dirigir la
rutina de exploración de teclas a su propia rutina, que puede verificar la
combinación de pulsaciones de teclas y MAYÚS , y actuar antes de que se imprima un carácter.

Dado que esta rutina viene después de la pulsación de tecla, pero antes de que se imprima,
este es un buen lugar para que la rutina del preprocesador compruebe si se
pulsa una tecla en particular. Un excelente ejemplo de un programa de este tipo es el programa
"VICword" de Mark Niggemann, el segundo libro de VIC de COMPUTE !.
Este programa agrega una rutina de lenguaje de máquina que verifica si
se presiona la tecla SHIFT o el logotipo de Commodore mientras no está en modo de cotización. Si encuentra
una de estas pulsaciones de tecla, sustituye una palabra clave BASIC completa por
la letra (AZ) de la tecla que se presionó. A
continuación se muestra una adaptación de ese programa para el 64.

100 SI PEEK (PEEK (56) * 256) <> 120THENPOKE56, PEEK (56) -1: CLR
110 HI = PEEK (56): BASE = HI * 256
120 PRINTCHR $ (147) "LECTURA DE DATOS"
130 PARA AD = 0 A 211: LEER POR
140 POKE BASE + ANUNCIO, POR: PRÓXIMO ANUNCIO
150:
200 AJUSTES DE REUBICACIÓN REM
210 POKE BASE + 26, HI: POKE BASE + 81, HI
220 POKE BASE + 123, HI: POKE BASE + 133, HI
230:
240 PRINT CHR $ (147) TAB (15) "*** 64WORD ***": PRINT
250 PRINT "PARA ACTIVAR / DESACTIVAR EL PROGRAMA:": PRINT: PRINT: PRINT "SYS"; BASE;
260 IMPRIMIR CHR $ (145); CHR $ (145);
270 DATOS 120,173,143,2,201,32
280 DATOS 208,12,169,220,141,143
290 DATOS 2,169,72,141,144,2
300 DATOS 88,96,169,32,141,143
310 DATOS 2,169,0,141,144,2
320 DATOS 88,96,165,212,208,117
330 DATOS 173,141,2,201,3,176
340 DATOS 110,201,0,240,106,169
350 DATOS 194,133,245,169,235,133
360 DATOS
370 95,201,11,11,93 56
380 DATOS 233,193,174,141,2,224
390 DATOS 2,208,3,24,105,26
400 DATOS 170,189,159,0,162,0
410 DATOS 134,198,170,160,158,132
420 DATOS 34,160,160,132,35,160
430 DATOS 0,10,240,16,202,16
440 DATOS 12,230,34,208,2,230
450 DATOS 35177, 34,16,246,48
460 DATOS 241,200,177,34,48,17
470 DATOS 8,142,211,0,230,198
480 DATOS 166,198,157,119,2,174
490 DATOS 211,0,40,208,234,230
500 DATOS 198,166,198,41,127,157
510 DATOS 199,2,230,198,169,20
520 DATOS 141,119,2,76,72,235
530 DATOS 76,224,234
550 FICHAS PARA REM tecla SHIFT
570 DATOS 153,175,199,135,161,129
580 DATOS 141,164,133,137,134,147
590 DATOS 202,181,159,151,163,201
600 DATOS 196,139,192,149,150,155
610 DATOS 191 138
630 REM fichas para COMMODORE cLAVE
www.unusedino.de/ec64/technical/project64/mapping_c64.html 32/126
25/9/2020 Mapping The C64
650 DATOS 152,165,198,131,128,130
660 DATOS 142,169,132,145,140,148
670 DATOS 195,187,160,194,166,200
680 DATOS 197,167,186,157,165,184
690 DATOS 190,158,0

Commodore 64word: Claves en comandos básicos

SHIFT clave Commodore


A IMPRIMIR #
B Y O
C CHR $ ASC
D LEER DATOS
E OBTENER FIN
F PARA EL SIGUIENTE
G GOSUB VOLVER
H AL PASO
I ENTRADA ENTRADA #
J GOTO EN
K DIM RESTAURAR
L CARGAR GUARDAR
M MEDIO $ LEN
N INT RND
O ABRIR CERRAR
P POKE PEEK
Q TAB (SPC (
R DERECHA $ IZQUIERDA $
S STR $ VAL
T SI ENTONCES
U TAN SQR
V VERIFICAR CMD
W DEF FN
X LIST FRE
Y SIN COS
Z RUN SYS

657 $ 291 MODE


Bandera: Habilita o deshabilita el cambio de juegos de caracteres con SHIFT /
pulsación de tecla del logotipo .

Esta bandera se utiliza para habilitar o deshabilitar la función que le permite


cambiar entre mayúsculas / gráficos y
juegos de caracteres en mayúsculas / minúsculas presionando las teclas SHIFT y el logotipo de Commodore simultáneamente.

Esta bandera afecta solo a esta función especial de la tecla MAYÚS y no


afecta a la impresión de caracteres con MAYÚS. Hacer un POKE con un valor de 128
($ 80) aquí desactivará esta función, mientras que un POKE con un valor de 0 la
habilitará una vez más. Se puede lograr el mismo efecto IMPRIMIENDO
CHR $ (8) o CTRL-H para deshabilitar el cambio de juegos de caracteres, y
CHR $ (9) o CTRL-I para habilitarlo. Ver entradas para ubicaciones 53272
($ D018) y 49152 ($ C000) para obtener más información sobre el cambio de
juegos de caracteres .

658 $ 292
Bandera AUTODN : Desplazamiento de pantalla habilitado

Esta ubicación se usa para determinar si mover el cursor más allá de la


cuadragésima columna de una línea lógica hará que
se agregue otra línea física a la línea lógica.

Un valor de 0 permite que la pantalla se desplace hacia abajo en las siguientes líneas
para agregar esa línea; cualquier valor distinto de cero desactivará el desplazamiento.
Esta bandera está configurada para deshabilitar el desplazamiento temporalmente cuando hay
caracteres esperando en el búfer del teclado (estos pueden incluir
caracteres de movimiento del cursor que eliminarían la necesidad de un desplazamiento).

Rango de ubicación: 659-663 ($ 293- $ 297)


Registros RS-232 Pseudo 6551

Para entrada / salida en serie a través del puerto RS-232, el software interno del
Commodore 64 emula el funcionamiento de un chip UART 6551 (que es
Receptor / Transmisor Asíncrono Universal, para sus aficionados a los acrónimos),
también conocido como un ACIA (Adaptador de interfaz de comunicaciones asincrónicas).

Estas ubicaciones de RAM se utilizan para imitar las funciones de los


registros de estado, control y comando de hardware de ese chip . Aunque las
ubicaciones de RAM se asignan para imitar la capacidad del 6551 de utilizar
un generador de velocidad en baudios integrado o un cristal de reloj externo,
el software interno no implementa esta función.

Se han tomado disposiciones para que el usuario se comunique con estos


se registra a través del comando RS-232 OPEN. Cuando se abre el dispositivo 2, se puede agregar un
nombre de archivo de hasta cuatro caracteres. Estos cuatro
caracteres se copian en las ubicaciones 659-662 ($ 293- $ 296), aunque los
dos últimos, que especifican una velocidad en baudios no estándar, no se utilizan porque
esa función no está implementada.

659 $ 293 M51CTR


RS-232: Mock 6551 Control Register

Esta ubicación se utiliza para controlar la


velocidad en baudios de E / S serie RS-232 (velocidad a la que se transmiten y reciben los datos), la longitud de la palabra
(número de bits por carácter de datos), y el número de bits de parada utilizados
para marcar el final de un carácter transmitido. Utiliza el mismo formato
como el del registro de control 6551 UART para configurar estos parámetros,
aunque, como verá, algunas de las configuraciones 6551 no son
implementadas por el software que emula el dispositivo UART. Por
ejemplo, las velocidades en baudios estándar que son superiores a 2400 baudios
www.unusedino.de/ec64/technical/project64/mapping_c64.html 33/126
25/9/2020 Mapping The C64
no se implementan, presumiblemente porque el software no puede mantener el ritmo a
velocidades más altas. Los significados de los distintos patrones de bits son los
siguientes:

Bit 7: STOP Bits


0 (valor de bit de 0) = 1 STOP Bit
1 (valor de bit de 128) = 0 Bits de STOP

Bits 6-5: WORD LENGTH


00 (valor de bit de 0) = 8 bits de DATOS
01 (valor de bit de 32) = 7 bits de DATOS
10 (valor de bit de 64) = 6 bits de DATOS
11 (valor de bit de 96) = 5 DATOS Bits

Bit 4:

Bits no utilizados 3-0: VELOCIDAD EN BAUDIOS


0000 (valor de bit de 0) = Velocidad no estándar (definida por el usuario) (No implementado)
0001 (valor de bit de 1) = 50 Baudios
0010 (valor de bit de 2) = 75 Baudios
0011 (valor de bit de 3) = 110 Baudios
0100 (valor de bit de 4) = 134.5 Baudios
0101 (valor de bit de 5) = 150 Baudios
0110 (valor de bit de 6) = 300 Baudios
0111 (valor de bit de 7) = 600 Baudios
1000 (valor de bit de 8) = 1200 Baudios
1001 (valor de bit de 9) = 1800 Baudios
1010 (valor de bit de 10) = 2400 Baudios
1011 (valor de bit de 11) = 3600 Baud (no implementado en el Commodore 64)
1100 (valor de bit de 12) = 4800 Baud (no implementado en el Commodore 64)
1101 (valor de bit de 13) = 7200 baudios (no implementado en el Commodore 64)
1110 (valor de bit de 14) = 9600 baudios (no implementado en el Commodore 64)
1111 (valor de bit de 15) = 19200 baudios (no implementado en el Commodore 64)

Este registro es el único que se debe configurar al abrir el


dispositivo RS-232 (número 2). El primer carácter del nombre del archivo se almacenará
aquí. Por ejemplo, la declaración OPEN 2,2,0, CHR $ (6 + 32) establecerá el
valor de esta ubicación en 38. Como puede ver en el gráfico anterior,
esto configura el dispositivo RS-232 para una transferencia de datos. velocidad de 300 baudios,
utilizando siete bits de datos por carácter y un bit de parada.

660 $ 294 M51CDR


RS-232: Registro de comando simulado 6551

Esta ubicación realiza la misma función que el


registro de comando del chip UART 6551 , que especifica el tipo de paridad, modo dúplex y
protocolo de protocolo de enlace.

El tipo de paridad utilizado determina cómo el 64 comprobará que los


datos RS-232 se reciben correctamente.

El modo dúplex puede ser dúplex completo (el 64 podrá


transmitir al mismo tiempo que recibe) o semidúplex (se
turnará para enviar y recibir).

El protocolo de intercambio tiene que ver con la manera en que el


dispositivo de envío le permite al receptor saber que está listo para enviar datos,
y el receptor le permite al remitente saber que ha recibido los datos
correctamente. Los significados de los patrones de bits en este registro son los
sigue:

Bits 7-5: Paridad


XX0 (valor de bit de
0,64,128 o 192) = Sin paridad generada o recibida
001 (valor de bit de 32) = Paridad impar transmitida y recibida
011 (valor de bit de 96) = Paridad par transmitida y Recibido
101 (valor de bit de 160) = Marcar paridad transmitida y recibida
111 (valor de bit de 224) = Paridad de espacio transmitida y recibida

Bit 4: Dúplex
0 (valor de bit de 0) = Dúplex completo
1 (valor de bit de 16) = Half Duplex

bits 3-1: Sin usar

bit 0: protocolo de enlace


(valor de bit 0) 0 = 3 Línea
(valor de bit de 1) 1 = X Línea

Este registro se puede ajustar a opción del usuario cuando abre RS-232
dispositivo (número 2). El segundo carácter del nombre del archivo se
almacenará aquí. Por ejemplo, la instrucción

OPEN 2,2,0, CHR $ (6 + 32) + CHR $ (32 + 16)

establecerá el valor de esta ubicación en 48, que es el valor del


segundo carácter en la parte del nombre de archivo de la declaración. Como puede
ver en el gráfico anterior, esto configura el dispositivo RS-232 para
la transferencia de datos semidúplex utilizando paridad impar y protocolo de enlace de tres líneas.

661-662 $ 295- $ 296 M51AJB


RS-232: Sincronización de bits no estándar

Estas ubicaciones se proporcionan para almacenar una


velocidad en baudios no estándar definida por el usuario , que se utilizará cuando el nybble bajo del registro de control en
659 ($ 293) se establezca en 0. Ellos fueron presumiblemente proporcionados para ajustarse a
el modelo del dispositivo 6551 UART, que permite
generar una velocidad en baudios no estándar a partir de un cristal de referencia externo. Sin embargo, la
www.unusedino.de/ec64/technical/project64/mapping_c64.html 34/126
25/9/2020 Mapping The C64
emulación de software de esa función no se proporciona en la
versión actual de Kernal y, por lo tanto, estas ubicaciones actualmente
no funcionan.

No obstante, Commodore ha especificado que si


se implementa la función de velocidad en baudios no estándar , el valor colocado aquí debe ser igual a la
frecuencia del reloj del sistema dividida por la velocidad en baudios dividida por 2 menos 100,
almacenada en orden de byte bajo y byte alto. La frecuencia de reloj del sistema para
los monitores de televisión estadounidenses (estándar NTSC) es 1.02273 MHz y para
los monitores europeos (estándar PAL) .98525 MHz.

663 $ 297 $ RSSTAT


RS-232: Mock 6551 Registro de estado

El contenido de este registro indica el estado de error de la


transmisión de datos RS-232 . Ese estado se puede determinar haciendo PEEKing en esta ubicación
directamente, haciendo referencia a la variable reservada BÁSICA ST, o usando
la rutina Kernal READST (65031, $ FE07).

Tenga en cuenta que si usa ST o Kernal, esta ubicación se establecerá en 0


después de que se lea. Por lo tanto, si necesita probar más de un bit,
asegúrese de que cada prueba conserve el valor original, ya que
no podrá volver a leerlo. El significado de cada valor de bit se
especifica a continuación:

Bit 7: 1 (valor de bit de 128) = Interrupción detectada


Bit 6: 1 (valor de bit de 64) = DTR (conjunto de datos listo) Falta señal
Bit 5:
Bit 4: 1 sin usar (valor de bit 16) = CTS ( Listo para enviar) Falta señal
Bit 3: 1 (valor de bit de 8) = Receptor Buffer Empty
Bit 2: 1 (valor de bit de 4) = Receptor Buffer Overrun
Bit 1: 1 (valor de bit de 2) = Error de trama
Bit 0: 1 (valor de bit de 1) = Error de paridad

El usuario es responsable para comprobar estos errores y tomar


las medidas adecuadas. Si, por ejemplo, encuentra que el bit 0 o 1 está establecido
cuando está enviando, lo que indica un error de paridad o de trama, debe
reenviar el último byte. Si se establece el Bit 2, el comando GET # 2 no se está
ejecutando lo suficientemente rápido como para vaciar el búfer (BASIC debería poder
mantener el ritmo a 300 baudios, pero no más alto). Si se establece el Bit 7, querrá
dejar de enviar y ejecutar un GET # 2 para ver qué se está enviando.

664 $ 298 BITNUM


RS-232: Número de bits que quedan por enviar / recibir

Esta ubicación se usa para determinar cuántos bits cero deben agregarse al
carácter de datos para completar su longitud hasta la longitud de palabra especificada
en 659 ($ 293).

665-666 $ 299- $ 29A BAUDOF


Tiempo requerido para enviar un bit

Esta ubicación contiene el valor de preescalador utilizado por los temporizadores A y B de CIA # 2.

Estos temporizadores provocan una interrupción NMI para controlar las


rutinas de transmisión y recepción RS-232, tiempos de RELOJ / PRESCALADOR. por segundo cada uno, donde CLOCK
es la frecuencia del sistema 02 de 1.022.730 Hz (985.250 si está utilizando
el estándar de televisión europeo PAL en lugar del estándar estadounidense NTSC
), y PRESCALER es el valor almacenado en 56580-1 ($ DD04-5) y
56582-3 ($ DD06 -7), en orden de byte bajo y byte alto. Puede utilizar la
siguiente fórmula para calcular el valor de preescalador correcto para una
velocidad en baudios RS-232 particular:

PRESCALER = ((CLOCK / BAUDRATE) / 2) -100

Los valores del preescalador americano (estándar NTSC) para las


velocidades en baudios estándar RS-232 que el registro de control en 659 ($ 293) pone a disposición
se almacenan en una tabla en 65218 ($ FEC2), comenzando con el
valor de dos bytes utilizado para 50 baudios. La versión europea (estándar PAL) de ese
La mesa se encuentra en 58604 ($ E4EC).

Rango de ubicación: 667-670 ($ 29B- $ 29E)


Índices de bytes al principio y al final de los búferes de recepción y transmisión

Los dos búferes de primero en entrar , primero en salir (FIFO) de 256 bytes para la
recepción y transmisión de datos RS-232 son envolventes dinámicos tampones. Esto significa
que el punto de inicio y el punto final del búfer pueden cambiar
con el tiempo, y cualquier punto puede estar en cualquier lugar dentro del búfer. Si,
por ejemplo, el punto de inicio está en el byte 100, el búfer se llenará
hasta el byte 255, momento en el que volverá al byte 0 nuevamente.
Para mantener este sistema, las siguientes cuatro ubicaciones se utilizan como
índices para el punto inicial y final de cada búfer.

667 $ 29B RIDBE


RS-232: Índice hasta el final del búfer de recepción

Este índice apunta al byte final dentro del


búfer de recepción RS-232 de 256 bytes y se utiliza para agregar datos a ese búfer.

668 $ 29C RIDBS


RS-232: Índice al inicio del búfer de recepción

Este índice apunta al byte de inicio dentro del


búfer de recepción RS-232 de 256 bytes y se utiliza para eliminar datos de ese búfer.

669 $ 29D RODBS


RS-232: Índice al inicio del búfer de transmisión

www.unusedino.de/ec64/technical/project64/mapping_c64.html 35/126
25/9/2020 Mapping The C64
Este índice apunta al byte de inicio dentro del
búfer de transmisión RS-232 de 256 bytes y se utiliza para eliminar datos de ese búfer.

670 $ 29E RODBE


RS-232: Índice hasta el final del búfer de transmisión

Este índice apunta al byte final dentro del


búfer de transmisión RS-232 de 256 bytes y se utiliza para agregar datos a ese búfer.

671-672 $ 29F- $ 2A0


Área de guardado de IRQTMP para vector de IRQ durante la E / S de casete

Las rutinas que leen y escriben datos de cinta son controladas por una
interrupción de IRQ . Para conectar una de estas rutinas a la interrupción,
el vector RAM IRQ en 788-789 ($ 314- $ 315) debe cambiarse para apuntar a
la dirección en la que comienza. Antes de que se realice ese cambio, la antigua
dirección de vector de IRQ se guarda en estas ubicaciones, de modo que después de que
finalice la E / S de la cinta
, se pueda restaurar la interrupción que se usa para escanear el teclado, verificar la tecla de parada y actualizar el reloj. .

Observará que todas las funciones anteriores se suspenderán durante la


E / S de cinta.

673 $ 2A1 ENABL


RS-232 Interrupciones habilitadas

Esta ubicación contiene el byte de indicador de interrupción NMI activo


del Registro de control de interrupciones CIA # 2 (56589, $ DD0D). Los valores de bit para esta
bandera son los siguientes:

Bit 4: 1 (valor de bit de 16) = El sistema está esperando el borde del receptor
Bit 1: 1 (valor de bit de 2) = El sistema está recibiendo datos
Bit 0: 1 (valor de bit de 1) = El sistema está transmitiendo datos

674 $ 2A2
Indicador de actividad del registro de control B CIA # 1 durante la E / S del casete

675 $ 2A3
Área de almacenamiento para el registro de control de interrupción CIA # 1 durante la lectura del casete

676 $ 2A4
Área de almacenamiento para CIA # 1 Registro de control A durante la lectura del casete

677 $ 2A5
Índice temporal a la siguiente línea de 40 columnas para desplazamiento de pantalla

678 $ 2A6
Bandera PAL / NTSC

Al encender, se realiza una prueba para ver si el El monitor utiliza el estándar de


televisión NTSC (norteamericano) o PAL (europeo).

Esta prueba se logra estableciendo una interrupción de trama para la línea de exploración
311 y probando si ocurre la interrupción. Dado que los monitores NTSC tienen
sólo 262 líneas de exploración de trama por pantalla, la interrupción se producirá sólo
si se utiliza un monitor PAL. Los resultados de esa prueba se almacenan aquí,
con un 0 que indica un sistema NTSC en uso y uno que indica un sistema PAL
.

Esta información es utilizada por las rutinas que establecen los


valores del preescalador para el temporizador de IRQ del sistema, de modo que la IRQ ocurre cada 1/60 de
segundo. Dado que el reloj del sistema PAL 02 funciona un poco más lento que la
versión NTSC , este valor de preescalador debe ajustarse en consecuencia.

679-767 $ 2A7- $ 2FF Sin


usar

El programador puede usar esta área para subrutinas de lenguaje de máquina o


para almacenamiento de datos gráficos.

Si el barco VIC-II está usando los 16K inferiores para gráficos y memoria
(la configuración predeterminada cuando el sistema está encendido), esta es una de las
pocas áreas libres disponibles para almacenar datos de sprites o personajes.
Las ubicaciones 704-767 podrían usarse para el bloque de datos número 11 del sprite,
sin interferir con el texto o las variables del programa BÁSICO.

Rango de ubicación: 768-779 ($ 300- $ 30B)


Tabla de vectores indirectos BÁSICA

Varias rutinas BÁSICAS importantes son vectorizadas a través de la RAM. Esto significa
que la primera instrucción ejecutada por la rutina es un salto indirecto
a una ubicación apuntada por uno de los vectores de esta tabla.

Al encender, el sistema establece estos vectores para que apunten a la siguiente


instrucción después de la instrucción JuMP original. La rutina luego
continúa con esa instrucción como si el salto nunca hubiera tenido lugar. Por
ejemplo, la rutina del mensaje de error BASIC comienza en 42039 ($ A437) con
la instrucción JMP ($ 300). El vector indirecto en 768 ($ 300) puntos
a 42042 ($ A43A), que es la instrucción que sigue inmediatamente a JMP
($ 300).

Aunque esto puede parecer una forma elegante de no lograr nada, el


uso de estos vectores indirectos tiene dos propósitos importantes. Primero, le
permite usar estas importantes rutinas BÁSICAS sin conocer sus
direcciones en la ROM BÁSICA.

Por ejemplo, la rutina para LISTAR el texto ASCII del


token de programa BASIC de un solo byte que se encuentra actualmente en el Acumulador (.A) se
www.unusedino.de/ec64/technical/project64/mapping_c64.html 36/126
25/9/2020 Mapping The C64
encuentra en una dirección en el VIC y otra en el 64. En futuras
computadoras Commodore, puede ser encontrado en otro lugar más. Sin embargo,
mientras la rutina esté vectorizada en RAM a 774 ($ 306), la declaración
QP = PEEK (774) + 256 * PEEK (775) encontraría la dirección de esa rutina en
cualquiera de las máquinas. Por lo tanto, ingresar tales rutinas a través de vectores RAM en
lugar de un salto directo a las ROM ayuda a mantener sus programas
compatibles con diferentes máquinas.

El otro efecto importante de tener estos vectores en RAM es que


puede alterarlos. De esa manera, puede redirigir estas importantes
rutinas BÁSICAS para ejecutar primero sus propias rutinas de preprocesamiento.

Si quisiera agregar comandos a BASIC, por ejemplo, ¿cómo lo haría


? Primero, necesitaría cambiar las rutinas BÁSICAS que
convierten el texto del programa ASCII al formato de programa tokenizado, de modo que cuando
se ingresó una línea de texto del programa, la nueva palabra clave se almacenaría como un
token.

A continuación, necesitaría cambiar la rutina que ejecuta los tokens, de modo


que cuando el intérprete llegue a su nuevo token de palabra clave,
tome la acción adecuada.

También tendría que cambiar la rutina que convierte los tokens de nuevo a
texto ASCII, de modo que su programa LISTARá el token correctamente.
Y es posible que desee modificar la rutina que imprime mensajes de error para
agregar nuevos mensajes para su palabra clave.

Como verá, los vectores de todas estas rutinas se pueden encontrar en la


siguiente tabla de vectores indirectos. Cambiar estos vectores es una
solución mucho más elegante y eficiente que la antigua técnica de cuña.
discutido en la ubicación 115 ($ 73)

768-769 $ 300- $ 301


Vector IERROR a la rutina de mensaje de error de impresión BÁSICA

Este vector apunta a la dirección de la rutina ERROR en 58251


($ E38B).

770-771 $ 302- $ 303


Vector IMAIN al bucle principal del programa BASIC

Este vector apunta a la dirección del bucle principal del programa BASIC en
42115 ($ A483). Ésta es la rutina que está funcionando cuando está en
modo directo (LISTO). Ejecuta sentencias o las almacena como
líneas de programa.

772-773 $ 304- $ 305 ICRNCH


Vector a la rutina que convierte el texto ASCII de palabras clave en
tokens

Este vector apunta a la dirección de la rutina CRUNCH en 42364


($ A57C).

774-775 $ 306- $ 307 IQPLOP


Vector a la rutina que enumera el token de programa BASIC como texto ASCII

Este vector apunta a la dirección de la rutina QPLOP en 42778


($ A71A).

776-777 $ 308- $ 309 IGONE


Vector a la rutina que ejecuta el siguiente token de programa BÁSICO

Este vector apunta a la dirección de la rutina GONE en 42980 ($ A7E4)


que ejecuta el siguiente token de programa.

778-779 $ 30A- $ 30B IEVAL


Vector a la rutina que evalúa una
expresión aritmética de un solo término

Este vector apunta a la dirección de la rutina EVAL t 44678 ($ AE86)


que, entre otras cosas, se usa para evaluar funciones BÁSICAS tales como
INT y ABS.

Rango de ubicación: 780-783 ($ 30C- $ 30F)


Área de almacenamiento de registros

El comando BASIC SYS usa esta área para almacenar 6510


registros internos : el acumulador (.A), los registros de índice .X y .Y y
el registro de estado. , .PAGS.

Antes de cada comando SYS, cada uno de los registros se carga con el
valor encontrado en la dirección de almacenamiento correspondiente. Una vez que el
programa ML terminó de ejecutarse y regresa a BASIC con una
instrucción RTS , el nuevo valor de cada registro se almacena en la
dirección de almacenamiento apropiada. Esto solo es cierto para SYS, no para el
comando USR similar.

Esta función le permite colocar los valores de pre-entrada necesarios en


los registros desde BASIC antes de SYS a Kernal o BASIC ML
rutina. También le permite examinar el efecto resultante de la
rutina en los registros y preservar la condición de los
registros al salir para las siguientes llamadas SYS.

Inmediatamente me viene a la mente una aplicación extremadamente práctica.


Aunque el BASIC 2 del 64 tiene muchos comandos para formatear
caracteres impresos en la pantalla del monitor (por ejemplo, TAB, SPC, PRINT A $, B),
no hay ninguno para ajustar la posición vertical del cursor.

www.unusedino.de/ec64/technical/project64/mapping_c64.html 37/126
25/9/2020 Mapping The C64
Hay una rutina Kernal, PLOT (58634, $ E50A), que le permitirá
colocar el cursor en cualquier lugar de la pantalla. Para usarlo,
primero debe borrar el indicador de acarreo (establecerlo en 0), y luego colocar el
número de columna horizontal deseado en el registro .Y y el vertical
número de fila en el registro .X antes de ingresar a la rutina con un SYS
65520. Usando el área de almacenamiento del registro, podemos imprimir el trabajo HELLO
en la fila 10, columna 5 con la siguiente línea BÁSICA:

POKE 781,10: POKE 782,5: POKE 783,0: SYS 65520: PRINT "HELLO"

También puede usar estas ubicaciones para ayudarlo a aprovechar las


rutinas de Kernal que devuelven información en el registro. Por ejemplo, la
rutina SCREEN (58629, $ E505) devuelve el número de filas de pantalla en el
registro .Y y el número de columnas en el registro .X. Usando esta
rutina, se podría escribir un programa BASIC para que se ejecute en máquinas con
diferentes formatos de pantalla (por ejemplo, el 64 y el VIC-20). Sólo
PEEK (781) después de SYS 65517 para ver cuántas columnas de
pantalla tiene la pantalla de la computadora.

780 $ 30C Área de


almacenamiento de SAREG para el registro .A (acumulador)

781 $ 30D SXREG


Área de almacenamiento para el registro de índice .X

782 $ 30E SYREG


Área de almacenamiento para el registro de índice

.Y 783 $ 30F Área de


almacenamiento SPREG para .P (estado) Registrar

el estado (.P) tiene siete banderas diferentes. Sus


asignaciones de bits son las siguientes:

Bit 7 (valor de bit de 128) =


Bit negativo 6 (valor de bit de 64) = Desbordamiento
Bit 5 (valor de bit de 32) = No utilizado
Bit 4 (valor de bit de 16) = BREAK
Bit 3 (valor de bit de 8) =
Bit decimal 2 (valor de bit de 4) = Desactivación de interrupción
Bit 1 (valor de bit de 2) = Cero
Bit 0 (valor de bit de 1) = Continuar

Si desea borrar cualquier bandera antes de un SYS, es seguro eliminarlos


todos con un POKE 783,0. Sin embargo, lo contrario no es cierto, ya que debe
tener cuidado con el indicador de desactivación de interrupciones.

Un 1 en este bit de bandera es igual a una instrucción SEI, que desactiva


todas las interrupciones de IRQ (como la que lee el teclado, por
ejemplo). ¡Apagar el teclado podría
dificultar el funcionamiento de la computadora ! Para configurar todos los indicadores, excepto la desactivación de interrupciones,
en 1, POKE 783,247.

784 $ 310 USRPOK


Instrucción de salto para la función de usuario ($ 4C)

El valor aquí (67, $ 4C) es la primera parte de la


instrucción JuMP del lenguaje de máquina 6510 para el comando USR.

785-786 $ 311- $ 312 USRADD


Dirección de la rutina USR (Byte bajo primero)

Estas ubicaciones contienen la dirección de destino del comando USR. Ellos


son inicializados por el sistema operativo para que señale el error básico
de rutina de manejo de mensajes, de modo que si se intenta ejecutar una llamada USR
sin cambiar estos valores, te duraran recibe una cantidad ILEGAL
mensaje de error.

Para ejecutar con éxito una llamada USR, primero debe hacer un POKE en
la dirección de destino en orden de bytes bajos y bytes altos. Puedes calcular
estos dos valores para cualquier dirección con la fórmula:

HI = INT (AD / 256): LO = AD- (HI * 256)

Por ejemplo, si la rutina USR comenzara en 49152 ($ C000),


POKE 786, INT ( 49152/256): POKE 785,49152- (PEEK (786) * 256 antes de
ejecutar el comando USR.

Lo que hace que el comando USR sea diferente de SYS es que puede pasar un
parámetro a la rutina del lenguaje máquina colocándolo entre
paréntesis después de la USR, y puede devolver un parámetro
a una variable asignando su valor a la función USR.

En otras palabras, la declaración X = USR (50) colocará primero el número 50


en formato de punto flotante en el acumulador de punto flotante ( FAC1) en
97-102 ($ 61- $ 66). Luego, el programa de lenguaje de máquina designado por
se ejecutará la dirección en este vector. Finalmente, a la variable X
se le asignará el valor de punto flotante que termina en FAC1 una vez finalizada
la rutina escrita por el usuario.

Dado que es difícil trabajar con la representación de punto flotante, es


útil cambiar estos parámetros de punto flotante a números enteros antes de
trabajar con ellos. Afortunadamente, existen rutinas vectorizadas que
harán las conversiones por usted. La rutina vectorizada en las ubicaciones
3-4 convierte el número en FAC1 en un entero con signo de dos bytes, con el
byte bajo en el registro .Y (y la ubicación 101 ($ 65)) y el byte alto
en el Acumulador (.A). Recuerde, ese número se convierte en un
entero con signo en el rango entre 32767 y -32768, con el Bit 7 del
www.unusedino.de/ec64/technical/project64/mapping_c64.html 38/126
25/9/2020 Mapping The C64
byte alto utilizado para indicar el signo.

Para devolver un valor a través de la función USR, debe colocar el


número en FAC1. Para conectar un entero con signo a
formato de coma flotante , coloque el byte alto en el acumulador (.A), el byte bajo
en el registro .Y y salte a través del vector en las ubicaciones 5-6
con una instrucción JMP ($ 0005). El resultado de coma flotante se
dejará en FAC1.

787 $ 313 Sin


usar

788-789 $ 314- $ 315


Vector CINV a la rutina de interrupción de IRQ

Este vector apunta a la dirección de la rutina que se ejecuta cuando


ocurre una interrupción de IRQ (normalmente 59953 ($ FA31)).

Al encender, el temporizador B CIA # 1 se configura para provocar una interrupción de IRQ


cada 1/60 de segundo. Este vector está configurado para apuntar a la rutina
que actualiza el reloj del software y la verificación de la tecla STOP, hace parpadear el
cursor, mantiene el bloqueo de la cinta y lee el teclado. Al
cambiar este vector, el usuario puede agregar o sustituir una
rutina en lenguaje máquina que también se ejecutará cada 1/60 de segundo. El
usuario que está escribiendo rutinas de interrupción de IRQ debe considerar lo
siguiente:

1. Es posible que ocurra una interrupción de IRQ mientras está


cambiando este vector, lo que causaría un error del cual no se
podría realizar ninguna recuperación. Por lo tanto, debe deshabilitar todas las IRQ
interrumpe antes de cambiar el contenido de esta ubicación, y vuelva
a habilitarlos después, usando las instrucciones 6510 SEI y CLI, o
usando la rutina Kernal VECTOR (64794, $ FD1A) para configurar este vector.

2. Hay algún código en la ROM que se ejecuta antes de que la


rutina de interrupción se dirija a través de este vector. Este código verifica si la
fuente de la interrupción fue una instrucción IRQ o BRK. Si primero
conserva el contenido de todos los registros empujándolos hacia la
pila en la siguiente secuencia: PHA, TXA, PHA, TYA, PHA. Depende
del usuario restaurar la pila al final de su rutina, ya sea
saliendo a través del IRQ normal, o con la secuencia: PLA, TAY, PLA,
TAX, PLA, RTI.

3. Solo hay un vector de IRQ, pero hay muchas fuentes para las
interrupciones de IRQ (dos chips CIA y varios IRQ de chips VIC). Si planea
habilitar IRQ de más de una fuente, la rutina de IRQ aquí debe
determinar la fuente y continuar la rutina en el
lugar apropiado para una IRQ de esa fuente.

Del mismo modo, si reemplaza la rutina de IRQ normal con la suya propia,
debe tener en cuenta que la exploración del teclado y la actualización del reloj
no se producirán a menos que llame a la rutina de interrupción anterior una vez cada 1/60 de
segundo. Se sugiere que si planea usar esa rutina,
guarde la dirección de vector anterior en alguna otra ubicación. De esa manera, tu
puede saltar a la rutina de interrupción del teclado a través de este
vector alternativo , en lugar de asumir que la dirección de la ROM nunca cambiará
y que es seguro saltar directamente a la ROM.

790-791 $ 316- $ 317


Vector CBINV : Interrupción de instrucción BRK

Este vector apunta a la dirección de la rutina que se


ejecutará cada vez que se encuentre una instrucción 6510 BRK (00).

El valor predeterminado apunta a una rutina que llama a varias de las


rutinas de inicialización de Kernal , como RESTOR, IOINIT y parte de CINT, y
luego salta a través del vector de inicio en caliente BÁSICO en 40962. Esta es la
misma rutina que se usa cuando STOP y RESTORE se presionan las teclas
simultáneamente, y actualmente se encuentra en 65126 ($ Fe66).

Un programa de monitor de lenguaje de máquina generalmente cambiará este vector para


apuntar a la dirección de inicio en caliente del monitor, de modo que se puedan
establecer puntos de interrupción que devolverán el control al monitor para fines de depuración.

792-793 $ 318- $ 319


Vector NMINV : Interrupción no enmascarable

Este vector apunta a la dirección de la rutina que se ejecutará


cuando se produzca una interrupción no enmascarable (NMI) (actualmente en 65095
($ FE47)).

Hay dos fuentes posibles para una interrupción NMI. La primera es la


tecla RESTORE, que está conectada directamente a la línea 6510 NMI. El
segundo es CIA # 2, cuya línea de interrupción está conectada al 6510
Línea NMI.

Cuando se produce una interrupción de NMI, una rutina de ROM establece el


indicador de desactivación de interrupciones y luego salta a través de este vector de RAM. El vector predeterminado
apunta a una rutina de interrupción que verifica cuál fue la causa del
NMI.

Si la causa fue CIA # 2, la rutina verifica si se


debe llamar a una de las rutinas RS-232. Si la fuente fue la tecla RESTORE,
busca un cartucho y, si está presente, el cartucho se ingresa en
el punto de entrada de inicio en caliente. Si no hay cartucho, se
prueba la tecla STOP . Si se presionó la tecla STOP al mismo tiempo que la
tecla RESTORE , varias de las rutinas de inicialización de Kernal, como RESTOR,
IOINIT y parte de CINT se ejecutan, y BASIC se ingresa a través de su
www.unusedino.de/ec64/technical/project64/mapping_c64.html 39/126
25/9/2020 Mapping The C64
vector de inicio en caliente en 40962. Si la tecla STOP no se presionó
simultáneamente con RESTORE, la interrupción terminará sin
que el usuario sepa que algo sucedió cuando la
tecla RESTORE fue presionado.

Dado que este vector controla el resultado de presionar la tecla RESTORE,


puede usarse para deshabilitar la secuencia STOP / RESTORE. Una forma sencilla de hacer
esto es cambiar este vector para que apunte a la instrucción RTI. Un
simple POKE 792,193 logrará esto. Para
restablecer el vector, POKE 792,71. Tenga en cuenta que esto eliminará todos los NMI, incluidos los
necesarios para las E / S RS-232.

Rango de ubicación: 794-813 ($ 31A- $ 32D)


Vectores Indirectos Kernal

Hay 39 rutinas Kernal para las cuales hay vectores en la


tabla de salto ubicada en la parte superior de la ROM (65409, $ FF81). Para diez de estas
rutinas, la entrada de la tabla de salto contiene una instrucción en lenguaje de máquina
para saltar a la dirección apuntada por el vector RAM en esta tabla.
Las direcciones de esta tabla se inicializan para apuntar a las
rutinas correspondientes en la ROM Kernal.
Sin embargo, dado que estas direcciones están en la RAM, se puede cambiar cualquier entrada en esta tabla. Esto permite
al usuario agregar a estas rutinas o reemplazarlas por completo.

Notará, por ejemplo, que muchas de estas rutinas involucran


funciones de Entrada / Salida. Al cambiar los vectores a estas rutinas,
es posible admitir nuevos dispositivos de E / S, como una unidad de disco IEEE
utilizada a través de un adaptador.

Se debe advertir al usuario que, dado que algunas de estas rutinas están
controladas por interrupciones, es peligroso cambiar estos vectores sin
desactivar primero todas las interrupciones. Para conocer un método seguro de cambiar todos
estos vectores a la vez, junto con los vectores de interrupción anteriores,
consulte la entrada de la rutina Kernal VECTOR en 64794 ($ FD1A).

Se puede encontrar información más específica sobre las rutinas individuales


en las descripciones dadas para sus ubicaciones ROM.

794-795 $ 31A- $ 31B IOPEN


Vector a Kernal OPEN Routine (Actualmente en 62282 ($ F34A))

796-797 $ 31C- $ 31D ICLOSE


Rutina de Vector a Kernal CLOSE (Actualmente en 62097 ($ F291))

798-799 $ 31E- $ 31F ICHKIN


Vector a Rutina Kernal CHKIN (Actualmente en 61966 ($ F20E))

800-801 $ 320- $ 321 ICKOUT


Vector a Rutina Kernal CKOUT ( Actualmente en 62032 ($ F250))

802-803 $ 322- $ 323 ICLRCH


Vector a Rutina Kernal CLRCHN (Actualmente en 62259 ($ F333))

804-805 $ 324- $ 325 IBASIN


Vector a Rutina Kernal CHRIN (Actualmente en 61783 ($ F157))

806-807 $ 326- $ 327 IBSOUT Rutina de


vector a kernal CHROUT (actualmente en 61898 ($ F1CA))

808-809 $ 328- $ 329 Rutina de


vector ISTOP a kernal STOP (actualmente en 63213 ($ F6ED))

Este vector apunta a la dirección de la rutina que prueba la


tecla STOP . La tecla STOP puede desactivarse cambiando esto con un POKE
808,239. Sin embargo, esto no desactivará la combinación STOP / RESTORE.
Para deshabilitar tanto STOP como STOP / RESTORE, POKE 808,234 (POKE 234 aquí
hará que el comando LIST no funcione correctamente). Para que las
cosas vuelvan a la normalidad en cualquier caso, POKE 808, 237.

810-811 $ 32A- $ 32B IGETIN


Vector a Kernal GETIN Routine (Actualmente en 61758 ($ F13E))

812-813 $ 32C- $ 32D ICLALL


Vector a Kernal Rutina CLALL (actualmente en 62255 ($ F32F))

814-815 $ 32E- $ 32F USRCMD


Vector a comando definido por el usuario (actualmente apunta a BRK en 65126
($ FE66))

Esto parece ser un vestigio de los días de PET, cuando el


monitor de lenguaje de máquina incorporado saltaba a través del vector USRCMD cuando
encontraba un comando que no entendía, lo que permitía al usuario
agregar nuevos comandos al monitor .

Aunque este vector se inicializa para apuntar a la rutina llamada por


STOP / RESTORE y la interrupción BRK, y es actualizado por la
rutina Kernal VECTOR (64794, $ FD1A), no parece tener la función
de ayudar en la adición de nuevos comandos.

816-817 $ 330- $ 331


Vector ILOAD a rutina de LOAD kernal (actualmente en 62622 ($ F49E))

818-819 $ 332- $ 333


Vector ISAVE : Rutina Kernal SAVE (actualmente en 62941 ($ F5DD))

820-827 $ 334- $ 33B Sin


usar

www.unusedino.de/ec64/technical/project64/mapping_c64.html 40/126
25/9/2020 Mapping The C64
Ocho bytes libres para vectores de usuario u otros datos.

828-1019 $ 33C- $ 3FB TBUFFER


Búfer de E / S de casete

Esta área de búfer de 192 bytes se utiliza para almacenar temporalmente los datos que se
leen o escriben en el dispositivo de cinta (dispositivo número 1).

Cuando no se usa para E / S de cinta, el búfer de casete ha sido durante mucho tiempo un
lugar favorito para que los programadores de Commodore
coloquen
rutinas de lenguaje de máquina cortas (aunque el 64 tiene 4K de RAM sin usar por encima de la ROM BÁSICA en 49152 ($ C000) que probablemente s
propósito).

De mayor interés práctico para el programador 64 es el posible uso de


esta área para la memoria gráfica del chip VIC-II (por ejemplo, forma de sprite
datos o datos de puntos de caracteres de texto). Si el chip VIC-II está almacenado en los
16K de memoria más bajos (como es la selección predeterminada), hay muy
poco espacio de memoria que se puede usar para cosas como
datos de forma de sprite sin conflictos. Si la cinta no está en uso, las ubicaciones 832-895
($ 340- $ 37F) se pueden usar como bloque de datos de sprite número 13, y las ubicaciones
896-959 ($ 380- $ 3BF) se pueden usar como bloque de datos de sprite número 14.

El Los tipos de bloques de cinta que se pueden almacenar aquí son


bloques de encabezado de programa , bloques de encabezado de datos y bloques de almacenamiento de datos.

El primer byte de cualquier tipo de bloque (que se almacena en la ubicación 828


($ 33C)) identifica el tipo de bloque. Los bloques de encabezado siguen esto
byte identificador con la dirección RAM inicial de dos bytes de los
datos de la cinta , la dirección RAM final de dos bytes y el nombre del archivo, rellenado con
espacios en blanco para que la longitud total de la parte del nombre sea igual a 187 bytes.
Los bloques de almacenamiento de datos tienen 191 bytes de datos después del
byte de identificación . Los significados de los distintos bloques identificadores son los siguientes:

un valor de 1 significa que el bloque es el encabezado de un


archivo de programa reubicable , mientras que un valor de 3 indica que el bloque es el
encabezado de un archivo de programa no reubicable.

Se crea un archivo reubicable cuando se GUARDA un programa con una


dirección secundaria de 0 (o cualquier número par), mientras que un archivo de programa no reubicable
se crea si la dirección secundaria SAVE es 1 (o cualquier número impar).
La diferencia entre los dos tipos de archivos es que un
programa no reubicable siempre se cargará en la dirección especificada en el encabezado. Un
programa reubicable se cargará en el inicio actual de la dirección BASIC a
menos que la instrucción LOAD use una dirección secundaria de 1, en cuyo caso
también se cargará en la dirección especificada en el encabezado.

Debe tener en cuenta que un archivo de programa usa el búfer de casete solo para
almacenar el bloque de encabezado. Los datos reales del programa se transfieren directamente
hacia o desde la RAM, sin que primero se almacenen en búfer.

Un valor de identificador de 4 significa que el bloque es un encabezado de archivo de datos.


Dicho bloque de encabezado se almacena en la memoria intermedia del casete siempre que un
programa BÁSICO ABRE un archivo de datos de cinta para lectura o escritura. Los
bloques de datos subsiguientes comienzan con un byte identificador de 2. Estos bloques contienen
el byte de datos real escrito por el comando PRINT # 1 y leídos por los
comandos GET # 1 e INPUT # 1. A diferencia del cuerpo de un archivo de programa,
estos bloques se almacenan temporalmente en la memoria intermedia del casete cuando se
escriben o leen.

Un byte identificador de 5 indica que este bloque es el final lógico


de la cinta. Esto indica al Kernal que no busque más allá de este punto,
incluso si hay bloques de cinta adicionales físicamente presentes en la
cinta.

1020-1023 $ 3FC- $ 3FF Sin


usar

Cuatro bytes libres más.

:::::::::::::::::::::::
:: Capítulo 4 ::
:: ::
:: 1K a 40K ::
:: ::
:: Memoria de pantalla, ::
:: Punteros de Sprite y ::
:: Texto del programa BÁSICO ::
:::::::::::::::::::::::

1024-2047 $ 400- $ 7FF VICSCN


Video Área de memoria de pantalla

Esta es la ubicación predeterminada del área de memoria de la pantalla de video, que


contiene la matriz de video y los punteros de datos de sprites.
Sin embargo, tenga en cuenta que el área de memoria de la pantalla de video se puede reubicar para comenzar
en cualquier límite de 1K. Su ubicación en un momento dado es
determinado por el registro de control de memoria del chip VIC-II en 53272
($ D018), y el banco de memoria VIC-II selecciona bits en el puerto de datos A de CIA # 2
(56576, $ DD00).

1024-2023 $ 400- $ 7E7


Matriz de video: 25 líneas por 40 columnas

La matriz de video es donde se almacenan los siguientes caracteres de pantalla en la RAM.


Normalmente, el chip VIC-II tratará cada byte de memoria aquí como un
código de visualización de pantalla y mostrará el carácter de texto que
www.unusedino.de/ec64/technical/project64/mapping_c64.html 41/126
25/9/2020 Mapping The C64
corresponde a ese byte de código. El primer byte de memoria aquí se
mostrará en la esquina superior izquierda de la pantalla, y los
bytes subsiguientes se mostrarán en las columnas a la derecha y las filas debajo de
ese carácter.

Es posible hacer que aparezcan caracteres de texto o gráficos en la


pantalla introduciendo sus códigos de pantalla directamente en esta área de la RAM.
Por ejemplo, la letra A tiene un valor de código de pantalla de 1. Por lo tanto,
POKE 1024,1 debería hacer que la letra A aparezca en la esquina superior izquierda de
la pantalla.

Sin embargo, debe tener en cuenta que la versión más actual del
sistema operativo inicializa la RAM de color que se utiliza para el
color de primer plano de los caracteres de texto al mismo valor que el
color de fondo cada vez que se borra la pantalla. El resultado es
que aunque el POKE pondrá una A azul en la pantalla, no
podrás verla porque es del mismo color azul que el fondo.
Esto puede remediarse introduciendo un valor diferente en la RAM de color
(que comienza en 55296 ($ D800)).

A POKE 1024,1: POKE 1024 + 54272,1 pondrá una A blanca en la


esquina superior izquierda de la pantalla. El bucle

FOR I = 0 TO 255: POKE 1024 + I, I: POKE 1024 + 54272 + I, 1: NEXT

mostrará todos los caracteres en blanco en la parte superior de la pantalla.


Otra solución al problema de la RAM de color es engañar al
sistema operativo para que inicialice la RAM de color por usted. Si cambia el
color de fondo al color de primer plano deseado antes de borrar la
pantalla, la RAM de color se establecerá en ese color. Luego, todo lo que tienes que hacer
es cambiar el color de fondo a lo que era. Este ejemplo
mostrará cómo se hace:

10 POKE 53281,2: EL FONDO REM ES ROJO


20 IMPRIMIR CHR $ (147): REM CLEAR SCREEN
30 POKE 53281,1: EL FONDO REM ES BLANCO
40 POKE 1024,1: REM ROJO APARECE "A" EN LA ESQUINA SUPERIOR IZQUIERDA

2040-2047 $ 7F8- $ 7FF


Punteros de datos de forma de sprite

Los últimos ocho bytes de la matriz de video (ya sea que esté aquí en la
ubicación predeterminada o se haya reubicado en otro lugar) se utilizan como
punteros a los bloques de datos utilizados para definir las formas de sprite.

Cada objeto tiene 3 bytes de ancho (24 bits) por 21 líneas de alto. Por lo tanto,
requiere 63 bytes para la definición de su forma, pero en realidad usa 64
bytes para llegar a 256 bloques de forma pares en el área
de 16K de RAM a la que se dirige el chip VIC-II.

Cada puntero contiene el bloque de datos actual que se utiliza para definir la
forma de un objeto. El número de bloque utilizado para definir la forma de
Sprite 0 se mantiene en la ubicación 2040 ($ 7F8), el bloque de forma Sprite 1 se
designa por la ubicación 2041 ($ 7F9), etc. El valor en el puntero
multiplicado por 64 es igual a la ubicación inicial de la tabla de datos de forma de sprite.
Por ejemplo, un valor de 11 en la ubicación 2040 indica que los
datos de forma para Sprite 0 comienzan en la dirección 704 (11 * 64) y continúan durante 63
bytes más hasta 767.

Para obtener información adicional sobre gráficos de sprites, consulte las entradas para
VIC individuales -II ubicaciones de gráficos de sprites de chips, y el resumen al
comienzo de la sección de chips VIC-II, en 53248 ($ D000).

2048-40959 $ 800- $ 9FFF


Texto del programa BÁSICO

Esta es el área donde se almacena el texto del programa BÁSICO real. El


texto de un programa BASIC consta de líneas enlazadas de tokens de programa.
Cada línea contiene lo siguiente:

1. Un puntero de dos bytes a la dirección de la siguiente línea de programa (en orden


estándar de bytes bajos y bytes altos). Después de la última línea del programa, un
puntero de enlace que consta de dos ceros marca el final del programa.

2. Un número de línea de dos bytes (también en orden de byte bajo y byte alto).

3. Los comandos del programa. Cada palabra clave se almacena como un carácter de un byte
cuyo valor es igual o mayor que 128. Print, por
ejemplo, se almacena como el número 151. Otros elementos del BASIC
El comando, como los nombres de las variables, los literales de cadena ("HOLA") y los
números, se almacenan utilizando sus equivalentes ASCII.

4. Un carácter 0, que actúa como terminador de línea. Para que


BASIC funcione correctamente, el primer carácter del área de texto BASIC
debe ser 0.

Una revisión rápida de los punteros BASIC comenzando en 43 ($ 2B) revela que
el diseño del área de programa BASIC (que va de
direcciones de memoria inferiores a superior) es el siguiente:

Texto de programa BÁSICO


Variables sin matriz y descriptores de cadena
Variables de matriz
Área libre (informada por FRE (0))
Área de texto de cadena (Las cadenas se construyen desde la parte superior de la memoria hacia abajo en el área libre)
ROM BÁSICA

Es interesante notar que el comando NEW no pone a cero el


www.unusedino.de/ec64/technical/project64/mapping_c64.html 42/126
25/9/2020 Mapping The C64
área de texto, sino que reemplaza la primera dirección de enlace en el
programa BASIC con dos ceros, indicando el final del programa. Por lo tanto,
puede recuperar un programa de un NUEVO reemplazando la primera
dirección de enlace , encontrando la dirección de los dos ceros que realmente marcan el
final del programa y estableciendo los punteros en 45, 47 y 49 (que
apuntan a la final de un programa BÁSICO antes de que el programa se ejecute) al
byte que sigue a estos ceros.

4096-8191 $ 1000- $ 1FFF


Imagen de ROM de caracteres para el chip VIC-II cuando se usa el banco de memoria 0 (predeterminado)

Aunque el chip VIC-II comparte memoria con el chip del procesador 6510,
no siempre ve esa memoria exactamente de la misma manera que el
microprocesador principal .

Aunque el 6510 accede a la RAM en estas ubicaciones, cuando el VIC-II está


almacenado para usar los primeros 16K de RAM (que es la condición predeterminada),
ve la ROM de caracteres aquí (el 6510 no puede acceder a esta ROM a menos
que se cambie a su memoria en 49152 ($ C000)). Esto resuelve el
enigma de cómo el chip VIC-II puede usar la ROM de caracteres en 49152
($ C000) para datos de forma de caracteres y RAM en 1024 ($ 400), cuando solo puede
abordar la memoria dentro de un rango de 16K. También significa que la RAM en
4096-8191 no se puede usar para la memoria de visualización de pantalla o
datos de puntos de caracteres definidos por el usuario , y los bloques de datos de sprites 64-127 no son accesibles.

Puede verificar esto activando los gráficos de mapa de bits con la


memoria de pantalla configurada para mostrar direcciones de 0 a 8192. Verá que la
parte inferior de la pantalla muestra todas las formas de caracteres de texto
almacenadas en la ROM. Para obtener más información sobre el formato de
almacenamiento de datos de caracteres de texto , consulte la descripción de la ROM de caracteres en
49152 ($ C000).

32768 $ 8000
Cartucho de ROM de
inicio

automático Un cartucho de ROM de inicio automático de 8K o 16K diseñado para usar esto como una dirección de memoria inicial se puede conectar
posterior. Si la ROM del cartucho en las ubicaciones 32772-32776 ($ 8004- $ 8008)
contiene los números 195, 194, 205, 56, 48 ($ C3, $ C2, $ CD, $ 38, $ 30)
cuando la computadora se enciende, iniciará el programa señalado por
el vector en las ubicaciones 32768-32769 ($ 8000- $ 8001), y usará
32770-32771 ($ 8002- $ 8003) para un vector de inicio en caliente cuando
se presione la tecla RESTORE . Estos caracteres son PETASCII para las letras inversas
CBM, seguidas de los dígitos 80. Un cartucho de
inicio automático también puede tener una dirección en 40960 ($ A000), donde reemplazaría a BASIC, o en 61440
($ F000), donde reemplazaría a Kernal. .

Es posible tener un cartucho de 16K en 32768 ($ 8000),


como el BASIC de Simon, que se puede encender y apagar para que
también se pueda usar la ROM BASIC que se encuentra debajo. Finalmente, incluso es posible tener
cartuchos seleccionados por banco, que activan y desactivan los bancos de memoria en el cartucho
alternativamente, de modo que un programa de 32K podría caber en solo 16K
de espacio de direccionamiento.

36864-40959 $ 9000- $ 9
Imagen de ROM de caracteres FFFF para el chip VIC-II cuando se utiliza el banco de memoria 2

Cuando el chip VIC-II está configurado para usar el tercer bloque de memoria de 16K
para gráficos (como sería el caso cuando se configura el 64 para emular
el PET, que tiene su memoria de pantalla de texto en 32768 ($ 8000), ve
la ROM del generador de caracteres en esta dirección (consulte la entrada en 4096 ($ 1000)
para obtener más detalles).

Cabe señalar que la ROM de caracteres es disponible solo cuando el


chip VIC-II está usando los bancos 0 o 2. Cuando usa uno de los otros dos
bancos, el usuario debe proporcionar todos los datos de forma de caracteres en una
tabla RAM .

::::::::::::::
:: Capítulo 5 ::
:: ::
:: 8K BASIC ::
:: ROM y 4K ::
:: RAM libre ::
::::::: ::::::: Las

ubicaciones 40960 a 49152 ($ A000 a $ BFFF) son utilizadas por la ROM BÁSICA
cuando se selecciona (que es la condición predeterminada). BASIC es el
programa principal del 64, que siempre se ejecuta si no hay un
cartucho de inicio automático insertado en el momento del encendido. Cuando el 64 te dice LISTO,
es BÁSICO hablar.

El intérprete BASIC que viene con el 64 es, además de estar


ubicado en un espacio de memoria diferente, casi idéntico al de Microsoft.
Intérprete BÁSICO que se encuentra en el VIC-20. Ambos intérpretes son
versiones ligeramente modificadas de PET BASIC 2.0, también conocido como PET BASIC
3.0 o Upgrade BASIC, porque era una versión mejorada del BASIC que se
encontraba en el PET original.

Esta es una bendición un tanto mixta, porque si bien PET BASIC, en su


día, citaba un lenguaje avanzado para usar con un
microprocesador de ocho bits , carece de varias de las características (como la
captura de errores ) que ahora son estándar en la mayoría de las computadoras domésticas. . Y, por
supuesto, no hace ninguna provisión para el uso fácil de las muchas
capacidades de gráficos y sonido que ofrecen los nuevos
chips de soporte de video y sonido dedicados .

www.unusedino.de/ec64/technical/project64/mapping_c64.html 43/126
25/9/2020 Mapping The C64
Por otro lado, su fidelidad al Commodore BASIC original
permite traducir una gran cantidad de software para el 64 con
pocos cambios (en la mayoría de los casos, el programa PET Emulator de Commodore
le permitirá ejecutar programas PET sin cambios). Las ayudas de programación
y los trucos desarrollados para PET y VIC, en su mayor parte, se
trasladarán bastante bien al 64. Aunque no hay una
lista de código fuente oficial de la ROM disponible en Commodore, esta versión
de BASIC ha existido el tiempo suficiente ha sido completamente
desmontado, disecado y documentado por usuarios de PET.

Las etiquetas utilizadas aquí corresponden a las utilizadas por Jim Butterfield en
sus mapas de memoria PET, que son bien conocidos entre los usuarios de PET BASIC. Por
lo tanto, deberían brindar alguna ayuda para localizar
rutinas equivalentes en las dos máquinas. Puede encontrar una buena descripción del funcionamiento de
PET BASIC en Programación de PET / CBM por Raeto West.

Está más allá del alcance de este libro detallar el funcionamiento interno de
cada rutina en el intérprete BASIC. Sin embargo, el siguiente resumen
de rutinas y sus funciones debería ayudar al usuario que esté interesado
en llamar rutinas BASIC desde su propio programa, o en modificar
el BASIC.

Tenga en cuenta que los puntos de entrada y salida enumerados para las rutinas
que realizan una función en particular deben usarse como guías, y
no absolutos. De hecho, BASIC ingresa a muchas de estas rutinas desde
lugares ligeramente diferentes para realizar diferentes tareas. Algunas
subrutinas son llamadas por tantos comandos que es difícil decir a
cuál pertenecen. Incluso encontrará que algunos comandos completos son
parte de otros comandos. Cuando sea importante para usted conocer los
detalles de una rutina en particular, necesitará obtener un desmontaje
de esa sección y mirar el programa en lenguaje de máquina en sí.

Cabe señalar que cuando no se necesita BASIC, se puede desconectar


y el chip VIC-II puede acceder a la RAM inferior y utilizarla
para gráficos de pantalla. Consulte la ubicación 56576 ($ DD00) para obtener más información.

40960-40961 $ A000- $ A001


Vector de arranque en frío

Este vector apunta a la dirección de la rutina utilizada para inicializar


BASIC. Una vez que el sistema operativo finaliza sus actividades de encendido,
ingresa al programa BASIC a través de este vector. El
efecto más visible de la rutina de inicialización BASIC es que la pantalla se
borra y las palabras:

**** COMMODORE 64 BASIC V2 ****

se imprimen junto con el mensaje BYTES FREE. Para obtener detalles de los
pasos tomados durante la inicialización de BASIC, consulte la entrada para
58260 ($ E394), el punto de entrada de arranque en frío actual.

40962-40963 $ A002- $ A003


Vector de

inicio en caliente El vector de inicio en caliente apunta a la dirección de las rutinas utilizadas para
restablezca BÁSICO después de presionar la combinación de teclas STOP / RESTORE. Esta
es la misma dirección a la que se vectoriza la instrucción BRK. Cuando
se ingresa BASIC a través de este vector, el programa en memoria no se ve
afectado. Para obtener más información, consulte la entrada de 58235 ($ E37B), el
punto de entrada de inicio en caliente actual.

40964-40971 $ A004- $ A00B


Caracteres de texto ASCII CBMBASIC

Los caracteres ASCII para las letras CBMBASIC se encuentran aquí.


Posiblemente un identificador, este texto no se hace referencia en ninguna otra parte del
programa.

40972041941 $ A00C- $ A051


Tabla de vectores de despacho de sentencias STMDSP

Esta tabla contiene vectores de dos bytes, cada uno de los cuales apunta a un
dirección que es un byte antes de la dirección de una de las rutinas
que realizan una instrucción BASIC.

Las declaraciones están en orden de número simbólico. Cuando llega el momento de


ejecutar una instrucción, la rutina NEWSTT en 42926 ($ A7AE) coloca esta
dirección-1 en la pila y salta a la rutina CHRGET. La
instrucción RTS al final de esa rutina hace que la dirección de la instrucción
se extraiga de la pila, se incremente y se coloque en el
Contador de programa , como si fuera la dirección de retorno real.

Esta tabla es útil para localizar la dirección de la rutina que


realiza una instrucción BASIC, de modo que la rutina se pueda desensamblar
y examinar. Para ayudar en este propósito, la tabla se reproduce a continuación.
con la dirección de destino real y no en el formato de dirección 1 utilizado
por BASIC.

Número de token Dirección de rutina de declaración


128 $ 80 FIN 43057 $ A831
129 $ 81 PARA 42818 $ A742
130 $ 82 SIGUIENTE 44318 $ AD1E
131 $ 83 DATOS 43256 $ A8F8
132 $ 84 ENTRADA # 43941 $ ABA5
133 $ 85 ENTRADA 43967 $ ABBF
134 $ 86 DIM 45185 $ B081
135 $ 87 LEER 44038 $ AC06
136 $ 88 LET 43429 $ A9A5
www.unusedino.de/ec64/technical/project64/mapping_c64.html 44/126
25/9/2020 Mapping The C64
137 $ 89 GOTO 43168 $ A8A0
138 $ 8A EJECUTAR 43121 $ A871
139 $ 8B IF 43304 $ A928
140 $ 8C RESTAURAR 43037 $ A81D
141 $ 8D GOSUB 43139 $ A883
142 $ 8E DEVOLVER 43218 $ A8D2
143 $ 8F REM 43323 $ A93B
144 $ 90 DETENER 43055 $ A82F
145 $ 91 EN 43339 $ A94B
146 $ 92 ESPERAR 47149 $ B82D
147 $ 93 CARGAR 57704 $ E168
148 $ 94 AHORRE 57686 $ E156
149 $ 95 $ E165 57701
150 $ 96 DEF 46003 $ B3B3
151 $ 97 POKE 47140 $ B824
152 $ 98 IMPRESIÓN # 43648 $ AA80
153 $ 99 IMPRESIÓN 43680 $ AAA0
154 $ 9A CONT 43095 $ A857
155 $ 9B LISTA 42652 $ A69C
156 $ 9C CLR 42590 $ A65E
157 $ 9D CMD 43654 $ AA86
158 $ 9E SYS 57642 $ E12A
159 $ 9F ABIERTO 57790 $ E1BE
160 $ A0 CLOSE 57799 $ E1C7
161 $ A1 GET 43899 $ AB7B
162 $ A2 NUEVO 42562 $ A642

41042-41087 $ A052- $ A07F FUNDSP


TABLE
Tabla de vectores de despacho de funciones

Esta tabla contiene vectores de dos bytes, cada uno de los cuales apunta a la
dirección de una de las rutinas que realiza una función BÁSICA.

Una función se distingue por el siguiente argumento, entre paréntesis.


La expresión entre paréntesis se evalúa primero mediante las rutinas
que comienzan en 44446 ($ AD9E). Luego, esta tabla se usa para encontrar la
dirección de la función que corresponde al número de token de la
función a ejecutar.

El contenido de esta tabla, que se puede utilizar para localizar las


direcciones de estas rutinas, se reproduce a continuación. Tenga en cuenta que la
dirección para la función USR es 784 ($ 310), que es la dirección de
la instrucción JMP que precede al vector proporcionado por el usuario.

Token # Función Dirección de rutina


180 $ B4 SGN 48185 $ BC39
181 $ B5 INT 48332 $ BCCC
182 $ B6 ABS 48216 $ BC58
183 $ B7 USR 784 $ 0310184
$ B8 FRE 45949 $ B37D
185 $ B9 POS 45982 $ B39E
186 $ BA SQR 49009 $ BF71
187 $ BB RND 57495 $ E097
188 $ BC LOG 45794 $ B9EA
189 $ BD EXP 49133 $ BFED
180 $ BE COS 57956 $ E264
191 $ BF SIN 57963 $ E26B
192 $ C0 TAN 58036 $ E2B4
193 $ C1 ATN 58126 $ E30E
194 $ C2 PEEK 47117 $ B80D
195 $ C3 LEN 46972 $ B77C
196 $ C4 STR $ 46181 $ B465
197 $ C5 VAL 47021 $ B7AD
198 $ C6 ASC 46987 $ B78B
199 $ C7 CHR $ 46828 $ B6EC
200 $ C8 IZQUIERDA $ 46848 $ B700
201 $ C9 DERECHA $ 46892 $ B72C
202 $ CA MEDIO $ 46903 $ B737

41088-41117 $ A080- $ A09D OPTAB


Tabla de vectores de despacho del operador

Esta tabla contiene vectores de dos bytes, cada uno de los cuales apunta a un
dirección que es un byte antes de la dirección de una de las rutinas
que realizan una operación matemática BÁSICA.

Para conocer el razonamiento detrás del desplazamiento de un byte a la dirección verdadera, consulte
la entrada de la ubicación 40972 ($ A00C). Además, cada entrada tiene un número de
un byte que indica el grado de precedencia que
toma la operación. Las operaciones con mayor grado de precedencia se
realizan antes que las operaciones de menor grado (por ejemplo, en la
expresión A = 3 + 4 * 6, la operación 4 * 6 se realiza primero y se
suma 3 al total). El orden en el que se realizan es:

1. Expresiones entre paréntesis


2. Exponencia (elevando a una potencia, usando el símbolo de flecha hacia arriba)
3. Negación de una expresión (-5, -A)
4. Multiplicación y división
5. Suma y resta
6. Pruebas de relación (=, <>, <,>, <=,> = todas tienen la misma precedencia)
7. NOT (operación lógica)
8. AND (operación lógica)
9. OR (operación lógica)

El contenido de esta tabla, que se puede utilizar para localizar las direcciones
de las rutinas matemáticas, se da a continuación. Tenga en cuenta que los
operadores menor que, igual y mayor que usan las mismas rutinas, aunque tienen
www.unusedino.de/ec64/technical/project64/mapping_c64.html 45/126
25/9/2020 Mapping The C64
diferentes números de token.

Token # Dirección de rutina del operador


170 $ AA + (AGREGAR) 47210 $ B86A
171 $ AB - (RESTA) 47187 $ B853
172 $ AC * (MULTIPLICAR) 47659 $ BA2B
173 $ AD / (DIVIDIR) 47890 $ BB12
174 $ AE ^ (EXPONENCIAR) 49019 $ BF7B
175 $ AF Y (LÓGICO Y) 45033 $ AFE9
176 $ B0 O (LÓGICO O) 45030 $ AFE6
177 $ B1> (MAYOR QUE) 49076 $ BFB4
178 $ B2 = (IGUAL A) 44756 $ AED4
179 $ B3 <(MENOS QUE) 45078 $ B016

41118-41373 $ A09E- $ A19D RESLST


Lista de palabras clave

Esta tabla contiene una lista completa de las palabras clave BÁSICAS reservadas
(aquellas combinaciones de caracteres de texto ASCII que hacen que BASIC haga
algo). Los caracteres de texto ASCII de estas palabras se almacenan en
orden de número de token. El bit # 7 de la última letra de cada palabra se establece en
indica el final de la palabra (la última letra tiene 128 agregados a su
verdadero valor ASCII).

Cuando se almacena el texto del programa BÁSICO, esta lista de palabras se utiliza para
reducir las palabras clave a un valor de un solo byte llamado token. El
comando PRINT, por ejemplo, no se almacena en un programa como cinco
bytes ASCII , sino como el token único 153 ($ 99).

Cuando el programa BASIC aparece en la lista, esta tabla se usa para convertir estos
tokens de nuevo a texto ASCII. Las entradas en esta tabla consisten en lo
siguiente:

1. Las declaraciones que se encuentran en STMDSP en 40972 ($ A00C), en el


orden de número de token indicado (números de token 128-162).

2. Algunas palabras clave diversas que nunca comienzan una declaración BÁSICA:

Token # Keyword
162 $ A3 TAB (
164 $ A4 A
165 $ A5 FN
166 $ A6 SPC (
167 $ A7 LUEGO
168 $ A8 NO
169 $ A9 PASO

3. Los operadores matemáticos encontrados en OPTAB en 41088 ($ A080), en el


orden del número de token indicados (números de token 170-179).

4. Las funciones que se encuentran en FUNDSP en 41042 ($ A052), en el


orden de número de token indicado (números de token 182-202).

5. La palabra GO (número de token 203 ($ CB) Esta palabra se agregó a la


tabla para que la declaración GO TO sea legal, para permitir cierta compatibilidad
con el primer PET BASIC, que permitía espacios dentro de las palabras clave.

41374-41767 $ A19E- $ A327 ERRTAB


Texto ASCII de los mensajes de error BASIC

Esta tabla contiene el texto ASCII de todos los mensajes de error BASIC.
Como en la tabla de palabras clave, el bit 7 de la última letra de cada mensaje se
establece para indicar el final del mensaje. Aunque todos hemos visto algunos
de ellos en un momento u otro, es algo abrumador ver la
lista completa a la vez. Los posibles errores que puede cometer incluyen:

1. DEMASIADOS ARCHIVOS
2. ARCHIVO ABIERTO
3. ARCHIVO NO ABIERTO
4. ARCHIVO NO ENCONTRADO
5. DISPOSITIVO NO PRESENTE
6. NO ENTRAR ARCHIVO
7. NO SALIR ARCHIVO
8. FALTA EL
NOMBRE DEL ARCHIVO 9. DISPOSITIVO ILEGAL NÚMERO
10. SIGUIENTE SIN PARA
11. SINTAXIS
12. VOLVER SIN GOSUB
13. SIN DATOS
14. CANTIDAD ILEGAL
15. DESBORDAMIENTO
16. FUERA DE LA MEMORIA
17. DECLARACIÓN DE UNDEF'D
18. SUSCRIPCIÓN MALA
19. ARREGLO
DE REDIM'D 20. DIVISIÓN POR CERO
21. DIRECTO ILEGAL
22. DIFUSIÓN DE TIPO
23. CADENA DEMASIADO
24. DATOS DE ARCHIVO
25. FÓRMULA DEMASIADO COMPLEJA
26. NO PUEDE CONTINUAR
27. FUNCIÓN UNDEF'D
28. VERIFICAR
29. LOAD El

mensaje número 30, BREAK, se encuentra en la


tabla de Mensajes varios a continuación.
www.unusedino.de/ec64/technical/project64/mapping_c64.html 46/126
25/9/2020 Mapping The C64

41768-41828 $ A328- $ A364


Tabla de vectores de mensajes de error

Esta tabla contiene la dirección de dos bytes de la primera letra de cada uno
de los 30 mensajes de error.

41829-41865 $ A365- $ A389


Mensajes varios

El texto de algunos de los otros mensajes que BASIC puede darle se


almacena aquí. Este texto incluye caracteres de movimiento del cursor y cada
mensaje termina con un carácter 0. Los mensajes son:

1) Retorno de carro, OK, retorno de carro


2) Espacio, espacio, ERROR
3) Espacio, IN, espacio
4) Retorno de carro, salto de línea, READY., Retorno de carro, salto de línea
5) Retorno de carro,

salto de línea, BREAK 41866 -41911 $ A38A- $ A3B7 FNDFOR


Buscar FOR en la pila

Esta rutina busca en la pila los bloques de entradas de datos que


se almacenan con cada comando FOR. Para obtener más información sobre los datos que
FOR coloca en la pila, consulte la ubicación 256 ($ 100).

41912 $ A3B8 BLTU


Abrir un espacio en la memoria para una nueva línea o variable de programa

Cuando se crea una nueva variable sin matriz, o cuando


se agrega o reemplaza una línea de programa BASIC , esta rutina se usa para dejar espacio para
la adición. Primero verifica si hay espacio disponible y luego
mueve el texto del programa y / o las variables para hacer espacio.

41979-41991 $ A3FB- $ A407 GETSTK


Verificación de espacio en la pila

Antes de realizar una operación que requiera espacio en la pila, esta


rutina se utiliza para verificar si hay suficiente espacio en la pila. Si
no lo hay, se emite un error FUERA DE MEMORIA.

41992-42036 $ A408- $ A434 RAZÓN


Verificar espacio en la memoria

Esta es la subrutina que verifica si hay suficiente espacio en


la memoria libre para adiciones propuestas, como nuevas líneas de texto del programa.
De lo contrario, solicita la recolección de basura, y si esto aún no
produce suficiente espacio, se emite un error FUERA DE MEMORIA.

42037-42088 $ A435- $ A468 OMERR SIN


MEMORIA Manejador de errores

Esta rutina solo establece el código del mensaje de error y pasa al


manejador de errores general.

42039-42088 $ A437- $ A468 ERROR


Manejador de errores general

El número de error se pasa a esta rutina en el registro .X y


muestra el mensaje de error correspondiente. Dado que esta rutina está
vectorizada a través de RAM a 768 ($ 300), puede desviar este vector a la
dirección de su propia rutina, que permitiría la captura de errores o la
adición de nuevos comandos.

42089-42099 $ A474- $ A47F LISTO


Imprimir LISTO

Esta rutina muestra la palabra LISTO, establece el indicador de mensaje Kernal para
mostrar que el modo directo está operativo y pasa al
bucle BÁSICO principal .

42112-42139 $ A480- $ A49B


Bucle principal PRINCIPAL , recibe la entrada y se ejecuta inmediatamente o almacena como
línea de programa

Este es el bucle principal del programa BÁSICO. Salta a través del vector RAM
en 770 ($ 302), por lo que esta rutina se puede desviar. La rutina obtiene una
línea de entrada del teclado y busca un número de línea. Si
hay un número de línea, el programa pasa a la rutina que
almacena una línea de texto del programa. Si no hay un número de línea, se
bifurca a la rutina que ejecuta declaraciones.

42140 $ A49C MAIN1


Agregar o reemplazar una línea de texto de programa

Esta rutina llama a subrutinas para obtener el número de línea, tokenizar


palabras clave y luego busca una línea con el mismo número de línea.

Si encuentra una línea con el mismo número, la rutina borra esa línea
moviendo todo el texto del programa y las variables superiores hasta donde
comenzó. Luego se agrega la nueva línea. Dado que se
llama a la rutina CLR , se pierde el valor de todas las variables del programa actual.

42291 $ A533 LINKPRG Volver a


vincular líneas de texto de programa con token

Cada línea de texto del programa comienza con un puntero a la dirección de la


www.unusedino.de/ec64/technical/project64/mapping_c64.html 47/126
25/9/2020 Mapping The C64
siguiente línea (dirección de enlace). Esta rutina escanea cada línea hasta el final
(que está marcada con un 0) y calcula la nueva dirección de enlace
agregando el desplazamiento a la dirección de la declaración actual.

42336 $ A560 INLIN Ingresar


una línea al búfer desde el teclado

Esta subrutina llama a la rutina Kernal CHRIN (61783, $ F157) para


obtener una línea de entrada desde el dispositivo de entrada actual (generalmente el
teclado). Almacena los caracteres en el búfer de entrada de texto BASIC en
512 ($ 200) hasta que se
reciba un retorno de carro o 89 caracteres . El dispositivo de teclado nunca devolverá más de 80
caracteres antes de un retorno de carro, pero otros dispositivos pueden generar una
línea más larga. Se producirá un error si la línea supera los 80 caracteres.

42361 $ A579 CRUNCH


Tokenizar línea en el búfer de entrada

Cuando se ingresa una línea de texto del programa en el búfer de texto BASIC
en 512 ($ 200), esta rutina pasa por la línea y cambia las
palabras clave o sus abreviaturas, que no aparecen entre comillas, en
su token correspondiente. Este comando se vectoriza a través de RAM en
772 ($ 304), por lo que se puede desviar para agregar nuevos comandos.

42515 $ A613 FINDLN


Búsqueda de número de línea

Esta rutina busca en el texto del programa, tratando de


número de línea entero de dos bytes que se almacena en 20-21 ($ 14- $ 15). Si se
encuentra, 95-96 ($ 5F- $ 60) se establecerá como un puntero a la dirección del
campo de enlace para esa línea, y se establecerá la bandera de acarreo . Si no
se encuentra, la bandera de acarreo se borrará.

42562 $ A642 SCRTCH


Realizar NUEVO

El comando NUEVO almacena dos ceros en la dirección de enlace de la primera


línea de programa para indicar el final del programa, y establece el
puntero de fin de programa en 45-46 ($ 2D- $ 2E) para señalar el byte más allá de esos
ceros. Continúa hasta el código de comando CLR.

42590 $ A65E CLEAR


Realizar CLR

El comando CLR cierra todos los archivos de E / S con la rutina Kernal CLALL
(62255, $ F32F). Elimina las variables de cadena copiando el
puntero de final de memoria en 55-56 ($ 37- $ 38) en la parte inferior del puntero de cadena en
51-52 ($ 33- $ 34). También copia el puntero al final del
texto del programa BASIC en 49-50 ($ 31- $ 31) al puntero al inicio de
las variables sin matriz en 45-46 ($ 2D- $ 2E) y al inicio de las variables de matriz
en 47- 48 ($ 2F- $ 30). Esto hace que estas variables sean inutilizables (aunque el
contenido de estas áreas no se borra realmente). Se llama
a RESTORE para que el puntero de datos vuelva al principio y se
borra la pila .

42638 $ A68E RUNC


Restablecer puntero al carácter de texto actual al comienzo del
texto del programa

Esta rutina restablece el puntero CHRGET TXTPTR (122-123, $ 7A- $ 7B) para
que el siguiente byte de texto que leerá el intérprete provenga del
principio del texto del programa.

52652 $ A69C LIST


Realizar LISTA

Esta rutina guarda el rango de líneas que se imprimirán en punteros en


95-96 ($ 5F- $ 60) y 20-21 ($ 14- $ 15), y luego las imprime,
traduciendo cualquier token a su Equivalente ASCII.

42775 $ A717 QPLOP


Imprimir tokens BÁSICOS como caracteres ASCII

Esta es la parte de la rutina LIST que cambia los


tokens de programa de un byte a sus caracteres de texto ASCII. La rutina está vectorizada a
través de RAM en 774 ($ 306), por lo que es posible listar un nuevo comando
palabras que ha agregado al cambiar este vector para desviar
su propia rutina.

42818 $ A742 FOR


Perform FOR

FOR se realiza principalmente al guardar la información necesaria para la SIGUIENTE


parte del comando en la pila (consulte la entrada de 256 ($ 100) para
obtener más detalles). Esto incluye el valor de terminación de TO, por lo que si el
límite superior es una variable, el valor actual de la variable se almacenará
y no puede finalizar el ciclo antes disminuyendo el valor de la
variable TO dentro del ciclo (aunque puede finalizarlo temprano aumentando
el valor de la variable FOR dentro del ciclo).

Además, dado que la expresión TO se evalúa solo una vez, en el momento FOR
se realiza, una declaración como FOR I = 1 TO I + 100 es válida. El
valor de terminación no se comprueba hasta que se ejecuta NEXT, por lo que las
sentencias de bucle siempre se ejecutan al menos una vez. La variable utilizada por FOR
debe ser una variable de coma flotante sin matriz. La reutilización de la misma
variable FOR en un bucle que aún está activo provocará la
cancelación del bucle FOR anterior y de todos los bucles intermedios.

www.unusedino.de/ec64/technical/project64/mapping_c64.html 48/126
25/9/2020 Mapping The C64
42926 $ A7AE NEWSTT
Configurar siguiente instrucción para ejecución

Esta rutina prueba la tecla STOP, actualiza el puntero al


número de línea actual y coloca el puntero de texto para leer el
comienzo de la declaración.

42980 $ A7E4 GONE


Leer y ejecutar la siguiente instrucción

Esta es la rutina que obtiene el siguiente token y ejecuta la


declaración. Está vectorizado a través de RAM en 776 ($ 308) para permitir la
adición y ejecución de nuevos tokens de declaración.

Dado que una instrucción siempre debe comenzar con un token o una
instrucción LET implícita , esta rutina verifica si el primer carácter es un
token válido. Si es así, la dirección se coloca en la pila, de modo que una
llamada a CHRGET volverá a la dirección del código que ejecuta
la declaración (consulte la tabla de tokens de declaración en 40972 ($ A00C)).

Un token no válido provocará un ERROR DE SINTAXIS. Un carácter cuyo


valor ASCII sea menor que 128 hará que se ejecute LET.

43037 $ A81D RESTOR


Realizar RESTAURAR

El comando RESTORE simplemente restablece el puntero DATA en 65-66 ($ 41- $ 42)


desde el inicio del puntero BASIC en 43-44 ($ 2B- $ 2V).

43052 $ A82C
Prueba de tecla STOP para interrupción en el programa

Desde aquí se llama a la rutina Kernal STOP y, si se


presiona la tecla, se ejecuta el comando STOP (63213, $ F6ED), a continuación.

43055 $ A831 END


Ejecutar END

El número de línea actual y los punteros de texto se conservan para un posible


comando CONT, y se imprime el mensaje READY. Si se
produce una rotura de la tecla STOP , primero se imprime el mensaje BREAK.

43095 $ A857 CONT


Realizar CONT

La declaración CONT se realiza moviendo los punteros guardados de nuevo a


la declaración actual y los punteros de carácter de texto actual. Si los
punteros guardados no se pueden recuperar,
se imprime la declaración de error CAN'T CONTINUE .

43121 $ A871 RUN


Realizar RUN

RUN se ejecuta llamando a la rutina Kernal SETMSG (65048, $ FE18) para


configurar el indicador de mensaje para el modo RUN y realizar un CLR para iniciar el
programa. Si una línea siguió a RUN, se ejecuta GOTO después de CLR.

43139 $ A883 GOSUB


Ejecutar GOSUB

Esta declaración empuja los punteros al carácter de texto actual y


la línea actual en la pila, junto con una constante 141 ($ 8D) que
identifica el bloque como información de GOSUB guardada para ser utilizada por RETURN.
Se llama GOTO.

43168 $ A8A0 GOTO


Realizar GOTO

Esta instrucción escanea BÁSICO para el número de línea de destino (el escaneo comienza
con la línea actual si el número de línea de destino es mayor, de lo contrario
, comienza con la primera línea). Cuando se encuentra la línea, los punteros
a la declaración actual y el carácter de texto se cambian, de modo que la
declaración de destino se ejecutará a continuación.

43218 $ A8D2 RETURN


Realizar RETURN

La instrucción RETURN busca los datos de GOSUB guardados en la pila y los usa
para restaurar los punteros a la línea actual y al carácter actual.
Esto hará que la ejecución continúe donde se detuvo cuando se
ejecutó GOSUB .

43256 $ A8F8 DATOS


Perform DATA

DATA usa la siguiente subrutina para encontrar el desplazamiento a la siguiente


declaración y agrega el desplazamiento a los punteros actuales para que
se ejecute la siguiente declaración. Si tiene efecto, omite la declaración,
al igual que REM.

43270 $ A906 DATAN


Buscar texto de programa para el final de la instrucción BASIC actual

Esta rutina comienza en el byte actual del texto del programa y busca
hasta encontrar un carácter cero (delimitador de línea) o dos puntos
que no está entre comillas (delimitador de instrucción) .

43304 $ A928 IF
www.unusedino.de/ec64/technical/project64/mapping_c64.html 49/126
25/9/2020 Mapping The C64
Perform IF

IF usa la rutina FRMEVL en 44446 ($ AD9E) para reducir la expresión


que sigue a un solo término. Si la expresión se evalúa como 0
(falso), la rutina pasa a REM. Si no es 0,
se ejecuta GOTO o la instrucción que sigue a THEN.

43323 $ A93B REM


Realizar REM

La instrucción REM se ejecuta omitiendo todo el texto del programa hasta el


comienzo de la siguiente instrucción. En realidad, es parte de la
instrucción IF , que continúa durante unos bytes después de la parte REM.

43339 $ A94B ONGOTO


Perform ON GOTO o ON GOSUB

ON se realiza convirtiendo el argumento en un número entero y luego


saltando un número entre comas cada vez que el número entero
disminuye hasta que el argumento llega a 0. Si un GOTO o GOSUB es el
siguiente token, el número actual entre comas se utiliza para ejecutar una
de esas declaraciones. Si los números entre comas se agotan antes de que
el argumento llegue a 0, la instrucción no tiene ningún efecto y
se ejecuta la siguiente instrucción.

43371 $ A96B LINGET


Convierta un número decimal ASCII en un número de línea binario de dos bytes

Esta subrutina es utilizada por varias instrucciones para leer un


número decimal , convertirlo en un número de línea entero de dos bytes (en
formato de byte bajo y byte alto ), y verifique que esté en el rango correcto de
0-63999.

43429 $ A9A5 LET


Realizar LET

El comando LET hace que las variables se creen e inicialicen, o


tener un nuevo valor asignado. Maneja todo tipo de
variables de matriz o no matriz : cadenas, punto flotante, enteros, ST, TI y TI $. La
rutina se compone de varias subrutinas que evalúan la variable,
evalúan la expresión asignada, verifican que el valor asignado sea
adecuado para una variable de ese tipo y luego asignan un valor a la
variable existente, o crean una nueva variable.

43648 $ AA80 PRINTN


Realizar PRINT #

La instrucción PRINT # llama a CMD y luego cierra el canal de salida con


la rutina Kernal CLRCHN (62259, $ F333).

43654 $ AA86 CMD


Realizar CMD

Esta rutina llama a la rutina Kernal CHKOUT (62032, $ F250) y llama


IMPRIMIR para enviar cualquier texto incluido al dispositivo. A diferencia de PRINT #,
deja abierto el canal de salida, de modo que la salida continúa yendo a ese
dispositivo.

43680 $ AAA0 PRINT


Realizar PRINT

La rutina PRINT tiene muchos segmentos, que son necesarios para las
distintas opciones que se le pueden agregar: TAB, SPC, comman,
punto y coma, variables, PI, ST, TI y TI $. Eventualmente, toda la salida se
convierte en cadenas y se llama a la rutina Kernal CHROUT para imprimir
cada carácter.

43806 $ AB1E STROUT


Imprimir mensaje de una cadena cuya dirección está en los
registros .Y y .A

Esta parte de la rutina PRINT genera una cadena cuya dirección está en
el acumulador (byte bajo) y el registro .Y (byte alto), y que termina
en un byte cero.

43853 $ AB4D DOAGIN


Mensaje de error de formateo de rutinas para GET, INPUT y READ

43899 $ AB7B GET


Realice GET y GET #

La rutina GET primero se asegura de que el programa no esté en


modo directo . Abre un canal de entrada usando la rutina Kernal CHKIN
(61966, $ F20E) si se agregó un signo de número para hacer GET #. Luego, llama a
las rutinas de E / S comunes en READ para obtener un solo carácter y hace que
el canal de entrada se cierre si se abre uno.

43941 $ ABA5 INPUTN


Realizar INPUT #

Esta rutina abre un canal de entrada con la rutina Kernal CHKIN,


llama a INPUT y luego cierra el canal con una rutina CHKOUT (62032,
$ F250). Los datos adicionales se descartan sin un mensaje EXTRA IGNORED, y
se emite un mensaje FILE DATA ERROR cuando el tipo de datos no es adecuado
para el tipo de variable utilizada.

43967 $ ABBF INPUT


Realizar INPUT
www.unusedino.de/ec64/technical/project64/mapping_c64.html 50/126
25/9/2020 Mapping The C64

La rutina INPUT verifica para asegurarse de que el modo directo no esté activo,
imprime avisos, recibe una línea de entrada del dispositivo y salta al
código común en READ que asigna la entrada a las variables que
fueron nombradas .

44038 $ AC06 READ


Ejecutar READ

Esta rutina incluye el comando READ y el código común para GET y


ENTRADA. El comando READ ubica el siguiente fragmento de DATOS, lee el
texto y lo convierte al tipo de datos apropiado para ser asignado
a una variable numérica o de cadena.

44284 $ ACFC EXIGNT


ASCII Texto para mensajes de error de entrada

El texto almacenado aquí es? EXTRA IGNORED y? REDO FROM START, cada uno
seguido de un retorno de carro y un byte cero.

44318 $ AD1E NEXT


Realizar SIGUIENTE

SIGUIENTE se ejecuta encontrando los datos FOR apropiados en la pila,


agregando el valor STEP a la variable FOR y comparando el resultado con
el valor TO. Si se completa el ciclo, las entradas de la pila para ese
comando FOR se eliminan de la pila. Si el bucle no ha alcanzado su
limit, los punteros a la declaración actual y el carácter de texto se
actualizan desde la entrada de la pila FOR, lo que hace que la ejecución continúe
con la declaración después de la declaración FOR.

44426 $ AD8A FRMNUM


Evaluar una expresión numérica y / o verificar si el tipo de datos no coincide.

Esta rutina se puede llamar desde diferentes puntos de entrada para verificar los
datos actuales con el tipo de datos deseado (cadena o numérico) para ver
si coinciden. Si no lo hacen, se producirá un error de TIPO INCORRECTO.

44446 $ AD9E FRMEVAL


Evaluar expresión

Este es el punto de inicio de un grupo muy poderoso de subrutinas


que BASIC utiliza ampliamente.

El propósito principal de estas rutinas es leer en el texto ASCII de las


expresiones BASIC, separar los operadores y términos de la expresión,
verificarlos en busca de errores, combinar los términos individuales realizando las
operaciones indicadas y obtener un valor único que el
programa BASIC puedo usar.

Esta puede ser una tarea muy compleja, y las expresiones pueden ser de
tipo cadena o numérico, y pueden contener cualquier tipo de variable, así como
constantes.

Al final, se establece la bandera que muestra si el valor resultante es una cadena


o numérico en 13 ($ D), y si el valor es numérico, la bandera en
14 ($ E) también se establece, para mostrar si es un número entero o de coma flotante
.

44675 $ AE83 EVAL


Convertir un solo numérico Plazo de texto ASCII a un punto flotante
Número

rutina Esto reduce un solo término aritmética que es parte de una


expresión en formato texto a su punto equivalente flotante.

Si el término es una constante, la rutina establece el indicador de tipo de datos en


número, establece el puntero de texto en el primer carácter numérico ASCII
y salta a la rutina que convierte la cadena ASCII en un
número de punto flotante .

Si el término es una variable, se recupera el valor de la variable. Si es


el carácter PI, el valor de PI se mueve al
acumulador de punto flotante .

Esta rutina se vectoriza a través de RAM en 778 ($ 30A).

44712 $ AEA8 PIVAL


PI expresado como un número de coma flotante de cinco bytes

El valor de PI se almacena aquí como un número de coma flotante de cinco bytes.

44785 $ AEF1 PARCHK


Evaluar expresión entre paréntesis

Esta rutina evalúa una expresión entre paréntesis llamando a las


rutinas de verificación de sintaxis que buscan abrir y cerrar
paréntesis, y luego llamando a FRMEVL (4446, $ AD9E) para cada nivel de
paréntesis.

44791 $ AEF7 CHKCLS


Verificar y omitir paréntesis de cierre

44794 $ AEFA CHKOPN


Verificar y omitir paréntesis de apertura

44799 $ AEFF CHKCOM


Verificar y omitir coma
www.unusedino.de/ec64/technical/project64/mapping_c64.html 51/126
25/9/2020 Mapping The C64

Este dispositivo de verificación de sintaxis es en esencia el mismo que las dos


rutinas de verificación anteriores. Se usa cuando el siguiente carácter debe ser
una coma. Si no es así, se produce un ERROR DE SINTAXIS. Si es así,
se omite el carácter y se lee el siguiente. Se
puede verificar y omitir cualquier carácter de esta manera cargando el carácter en
el Acumulador e ingresando esta rutina desde SYNCHR en 44799
($ AEFF).

44808 $ AF08 SNERR


Mensaje de error de sintaxis de impresión

44843 $ AF2B ISVAR


Obtener el valor de una variable

44967 $ AFA7 ISFUN


Despachar y evaluar una función

Si una función BÁSICA (como ASC ("A")) es parte de una expresión, esto
La rutina usará la tabla de despacho de funciones en 42242 ($ A502) para configurar
la dirección de la rutina de función adecuada, y luego se bifurcará a esa
rutina.

45030 $ AFE6 OROP


Realizar OR

La rutina OR establece el registro .Y como un indicador y pasa a


la rutina AND, que también realiza OR.

45033 $ AFE9 ANDOP


Realizar Y

La rutina AND cambia los parámetros a valores enteros de dos bytes y


realiza la operación lógica adecuada (Y u O). Un resultado de 0
significa falso, mientras que un resultado de -1 significa verdadero.

45078 $ B016 DORE1


Realizar comparaciones

Esta rutina hace las comparaciones mayor que (>), menor que (<) e igual (=)
para los números y cadenas de puntos de inflado. El resultado en el
acumulador de punto flotante será 0 si la comparación es falsa y
-1 si es verdadera.

45185 $ B018 DIM


Realizar DIM

Este comando llama a la siguiente rutina para crear una matriz para cada
variable dimensionada (ya que una declaración puede tomar la forma DIM A (12),
B (13), C (14) ...). Si se hace referencia al elemento de matriz antes de una
instrucción DIM (por ejemplo, A (3) = 4), la matriz se dimensionará a 10
(como si se ejecutara DIM A (10)). Recuerde, DIMensionar una matriz a
10 realmente crea 11 elementos (10). El elemento 0 siempre debe ser
considerado al calcular el tamaño para DIMensionar su matriz.

45195 $ B08B PTRGET


Buscar una variable y configurarla si no se encuentra

Esta rutina intenta ubicar una variable buscando su nombre


en el área de variables. Si no se puede
encontrar una variable existente con ese nombre , se crea una con la rutina NOTFNS a continuación.

45331 $ B113
Verificar si el registro .A contiene caracteres alfabéticos ASCII

Esto es parte de la verificación de un nombre de variable válido (debe comenzar


con un carácter alfabético).

45341 $ B11D NOTFNS


Crear una nueva variable BÁSICA

Esta rutina deja espacio para un descriptor de siete bytes moviendo el


área de almacenamiento variable siete bytes más arriba en la memoria, y luego crea
el descriptor.

45445 $ B185 FINPTR


Devuelve la dirección de la variable que fue encontrada o creada

Esta rutina almacena la dirección de la variable que fue encontrada o


creada por las rutinas anteriores en un puntero en 71-72 ($ 47- $ 48).

45460 $ B194 ARYGET


Asignar espacio para descriptores de matriz

Esta rutina asigna cinco bytes más dos bytes para cada dimensión
especificada para el descriptor de matriz.

45477 $ B1A5 N32768


La constante -32768 en formato de coma flotante de cinco bytes

Esta constante se utiliza para verificar el rango en la conversión de un


número de punto flotante a un entero con signo (el valor intermedio mínimo es
-32768).

45482 $ B1AA
Convertir un número de coma flotante en un entero con signo en los registros .A y .Y

Esta subrutina llama a AYINT, a continuación, que verifica que el


www.unusedino.de/ec64/technical/project64/mapping_c64.html 52/126
25/9/2020 Mapping The C64
número en el acumulador de coma flotante esté entre 32767 y -32768,
y lo convierte a un entero de 16 bits con signo en 100-101 ($ 64- $ 65),
primero el byte alto . Deja el byte alto del entero en el
acumulador y el byte bajo en el registro .Y.

Aunque esta rutina no parece estar referenciada en ninguna parte de


BASIC, el vector en las ubicaciones 3-4 apunta a su dirección. Presuntamente,
se proporciona en beneficio del usuario que desea pasar
parámetros en una llamada USR, o similares.

45490 $ B1B2 INTIDX


Ingrese y

convierta un subíndice de coma flotante en un entero positivo Esta rutina convierte un valor de subíndice de coma flotante en un entero,
asegurándose primero de que sea positivo.

45503 $ B1BF AYINT


Convertir un número de coma flotante en un entero con signo

Esta subrutina primero verifica para asegurarse de que el número en el


acumulador de coma flotante esté entre 32767 y -32768. Si no es así, se produce
un error de CANTIDAD ILEGAL. Si es así, la rutina lo convierte
en un entero de 16 bits con signo con el byte alto en la ubicación 100 ($ 64)
y el byte bajo en la ubicación 101 ($ 65).

45521 $ B1D1 ISARIO


Buscar un elemento de matriz o crear una nueva matriz en la RAM

Esta rutina busca una matriz. Si se encuentra,


se comprueba el valor del subíndice para ver si es válido y se establecen los punteros a la matriz y al
elemento de la matriz. Si no se encuentra, se
crea la matriz y se establecen los punteros.

45637 $ B245 BSERR


Imprimir MALA SUBSCRIPT Mensaje de error

45640 $ B248 FCERR


Imprimir CANTIDAD ILEGAL Mensaje de error

45900 $ B34C UMULT


Calcular el tamaño de una matriz multidimensional

Esta rutina calcula el tamaño de una matriz multidimensional


multiplicando las dimensiones.

45949 $ B37D FRE


Realizar FRE

La función FRE llama a la rutina de recolección de basura en 46374 ($ B526)


para deshacerse del texto de cadena no utilizado y calcula la diferencia
entre la parte inferior del texto de cadena y la parte superior del almacenamiento de matriz. Es
entonces cae a través de la rutina de seguimiento, que supone que la libre
valor de la memoria es un entero de 16 bits, y la convierte en flotante
punto en consecuencia.

Por supuesto, mientras que el espacio de memoria libre en el PET siempre pudo haber
sido 32767 o menos (el valor máximo de un entero con signo),
definitivamente no es el caso en el 64. Debido a que la conversión es de un
entero con signo, cualquier valor de memoria sobre 32767 se considerará
negativo (el bit alto se trata como un bit de signo). Por lo tanto, para
estos valores más altos debe agregar el doble del valor de bit del bit alto
(65536) para obtener el valor correcto. La expresión
FRE (0) -6556 * (FRE (0) <0) siempre devolverá la cantidad correcta de
memoria libre .

45969 $ B391 GIVAYF


Convertir entero

de
16 bits con signo en punto flotante Esta rutina trata el valor en el acumulador como el byte alto de un entero de 16 bits con signo, y el valo
byte bajo , y convierte el valor con signo entero en un número de punto flotante en
el acumulador de punto flotante.

La dirección de esta rutina es apuntada por el vector RAM en 5-6,


y la rutina se puede usar para devolver un argumento de la llamada USR en
el acumulador de punto flotante.

45982 $ B39E POS


Perform POS

El comando POS llama a la rutina Kernal PLOT (58634, $ E50A) para obtener
la posición del cursor en la línea lógica. Lo que realmente hace
es un equivalente de PEEK (211). Recuerde, dado que se trata de una
línea lógica, este número puede ser superior a 39. El enunciado "ESTA
ORACIÓN ES MÁS LARGA QUE UNA LÍNEA FÍSICA", POS (X) devolverá un valor
de 48 para el POS (X).

45990 $ B3A6 ERRDIR


Verifique si el programa se está ejecutando en modo directo y, si es así, emite un error

Esta rutina es llamada por sentencias que prohíben la ejecución en


modo directo . Comprueba una bandera que se establece cuando una línea sin un número de línea
se ingresa, y causa un error DIRECTO ILEGAL si se establece la bandera.

46003 $ B3B3 DEF


Realizar DEF

DEF realiza una comprobación de sintaxis y coloca cinco bytes en la


www.unusedino.de/ec64/technical/project64/mapping_c64.html 53/126
25/9/2020 Mapping The C64
pila: el primer byte de la declaración de función, un puntero de dos bytes
a la variable dependiente (la X en FN (X)) y la dirección del
primer carácter de la propia definición, donde reside en el
texto del programa.

La instrucción DEF debe caber en una línea, pero las funciones se pueden extender
anidando (haciendo que una función llame a otra).

46049 $ B3E1 GETFNM


Verificar la sintaxis DEF y FN

Esta rutina verifica para asegurarse de que FN siga a SEG, y que el


dependent variable has a valid floating point variable name. It calls
the routine to find or create a variable to get the pointer to its
address.

46068 $B3F4 FNDOER


Perform FN

The FN evaluation is done by evaluating the FN argument (for example,


FN(A+B*C/D)) and then getting the rest of the expression from the text
of the function definition statement. The function variable
descriptor area is used as a work area, and the dependent variable is
not disturbed (so that if the definition used FN(X), the value of X
will not be changed by the function call).

46181 $B465 STRD


Perform STR$

STR $ primero verifica para asegurarse de que el parámetro sea un número y


luego llama a las rutinas que convierten el punto flotante a ASCII y empaquetan
los punteros en una constante de cadena.

46215 $ B487 STRLIT


Escanear y configurar punteros a una cadena en la memoria

Esta rutina calcula la longitud de la cadena y llama a la


rutina que asigna espacio en la memoria. Luego guarda la cadena o
crea un puntero a su ubicación en el búfer de entrada de texto BÁSICO en
512 ($ 200).

46324 $ B4F4 GETSPA


Asignar espacio en memoria para cadena

La cantidad de espacio necesario para una cadena se pasa a esta rutina, y


la rutina verifica si hay esa cantidad de espacio disponible en
memoria. Si no, realiza una recolección de basura y vuelve a intentarlo.

46374 $ B526 GARBAG


Recolección de basura de cadenas

Siempre que se cambia una cadena de alguna manera, la versión revisada del
texto se agrega al final del área de texto de la cadena, dejando la
versión anterior más arriba en la memoria, desperdiciando espacio.

Para recuperar ese espacio, se debe buscar el descriptor de cada cadena cuyo
texto está en el área de texto de cadena (en lugar de en el área de texto del programa)
para encontrar el texto válido que está más alto en la memoria. Si
esa cadena no es tan alta como podría ser, se mueve hacia arriba para reemplazar
cualquier cadena que ya no sea válida. Entonces toda la cuerda
los descriptores deben buscarse nuevamente para encontrar la siguiente cadena más alta y
moverla hacia arriba. Esto continúa hasta que se hayan
cubierto todas las cuerdas que no se utilizan . Después de que todos se hayan movido hacia arriba, el puntero al final del
texto de la cadena en 51-52 ($ 33- $ 34) se cambia para mostrar la nueva
ubicación inferior .

Si hay más de unas pocas cadenas cuyo texto está en el


área de almacenamiento de texto de cadenas , en lugar de en el cuerpo del programa, escanear cada
cadena tantas veces como cadenas haya puede llevar mucho
tiempo. La computadora puede parecer como si hubiera muerto (la tecla STOP ni
siquiera se verifica durante el procedimiento).

La recolección tardará aproximadamente el mismo tiempo que haya sobrante


espacio o no; la recolección completa se hará incluso si se hace
inmediatamente después de la última recolección. Aunque la mayor
capacidad de memoria del 64 ayuda a evitar la necesidad de recolección de basura,
un programa grande con muchas matrices de cadenas puede experimentar
retrasos prolongados en la recolección.

46525 $ B5BD
Verificar la cadena más elegible para recolectar

Esta parte de la rutina de recolección de basura verifica si la


cadena actual es la más alta en la memoria.

46598 $ B606
Recolectar una cadena

Esta parte de la rutina de recolección de basura mueve la cadena a


memoria alta y actualiza el descriptor para que apunte a su nueva ubicación.

46653 $ B63D GATO


Concatenar dos cadenas

Esta rutina se usa para agregar el texto de una cadena al final de


otra (A $ + B $). La verificación de errores se realiza para ver si la longitud de la
cadena combinada está dentro del rango, se llama a la rutina de asignación para
asignar espacio y la nueva cadena se construye en la parte inferior del
www.unusedino.de/ec64/technical/project64/mapping_c64.html 54/126
25/9/2020 Mapping The C64
área de texto de la cadena.

46714 $ B67A MOVINS


Mover una cadena en la memoria

Esta es la rutina que se utiliza para mover una cadena al final del
área de texto de la cadena para la rutina anterior. Generalmente se utiliza como
rutina de utilidad para mover cadenas.

46755 $ B6A3 FRESTR


Descartar una cadena temporal

Esta rutina llama a la siguiente rutina que borra una entrada de


la pila de descriptores temporales. Si el descriptor estaba en la pila,
sale después de establecer punteros a la cadena y su longitud. Si no
estaba en la pila temporal y está en la parte inferior del
almacenamiento de texto de la cadena , el puntero hacia la parte inferior se mueve hacia arriba para desasignar la
cadena.

46811 $ B6DB FRETMS


Eliminar una entrada de la pila de descriptores de cadena

Si el descriptor de una cadena válida actualmente es el mismo que una de


las entradas de la pila de descriptores de cadena temporal, la entrada de la pila
se elimina.

46828 $ B6EC CHRD


Ejecutar CHR $

La rutina CHR $ crea un descriptor en la pila de cadenas temporal


para la cadena de un byte cuyo valor se especifica en el comando y
establece un puntero a esa cadena.

46848 $ B700 LEFTD


Perform LEFT $

LEFT $ crea un descriptor de cadena temporal para una nueva cadena que
contiene el número de caracteres del lado izquierdo de la cadena
que se especifica en el comando.

46892 $ B72C RIGHTD


Perform RIGHT $

RIGHT $ manipula sus parámetros para que el final de LEFT $ pueda


usarse para crear un descriptor de cadena temporal para una nueva cadena. Esta
nueva cadena contiene el número de caracteres del lado derecho de
la cadena que se especifica en el comando.

46903 $ B737 MEDIO


Perform MID $

MID $ manipula sus parámetros para que el final de LEFT $ se pueda


usar para crear un descriptor de cadena temporal para una nueva cadena. Esta
nueva cadena contiene el número de caracteres de la posición en el
medio de la cadena que se especifica en el comando.

46945 $ B761 PREAM


Extraer parámetros de la función de cadena de la pila para LEFT $, RIGHT $ y MID $

Esta rutina se utiliza para obtener los dos primeros parámetros para los tres
comandos.

46972 $ B77C LEN


Realizar LEN

La función LEN se realiza obteniendo la longitud de la cadena del


descriptor y convirtiéndola en un número de coma flotante.

46987 $ B78B ASC


Realizar ASC

Esta rutina obtiene el primer carácter de la cadena en el registro .Y


(si no es una cadena nula). Luego llama a la parte de POS que
convierte un entero de un byte en .Y en un número de coma flotante.

47003 $ B79B GETBYTC Ingresar


un parámetro cuyo valor esté entre 0 y 255

Esta rutina lee el texto numérico del programa ASCII, lo convierte en un


número entero, verifica que esté en el rango 0-255 y lo almacena en el
registro .X . Esta rutina puede ser útil para leer parámetros de una
declaración USR o nuevos comandos.

47021 $ B7AD VAL


Ejecutar VAL

La rutina VAL obtiene el puntero de cadena y lee la cadena uno


carácter a la vez hasta que se encuentre un carácter no válido (los
números ASCII , el carácter de signo, un solo punto decimal, el exponente y los espacios
son todos válidos). Luego, la cadena se cambia a punto flotante. Si no
se encuentran caracteres válidos, se devuelve un 0.

47083 $ B7EB GETNUM


Obtenga un parámetro de dirección de 16 bits y un parámetro de 8 bits (para POKE y WAIT)

Esta rutina obtiene el siguiente parámetro numérico del lugar actual en el


texto del programa. La rutina lo evalúa, comprueba que sea un
entero positivo dentro del rango 0-65535 y lo cambia de punto flotante
www.unusedino.de/ec64/technical/project64/mapping_c64.html 55/126
25/9/2020 Mapping The C64
a un entero de dos bytes en 20-21 ($ 14- $ 15). Busca y omite una
coma, luego obtiene un parámetro entero de un byte en el registro .X. los
La rutina se utiliza para obtener los parámetros de POKE y WAIT.

47095 $ B7F7 GETADR


Convertir un número de coma flotante en un entero de dos bytes sin signo

Esta rutina verifica el número en el acumulador de coma flotante para


asegurarse de que sea un número positivo menor que 65536, y luego llama a
la subrutina que conecta el punto flotante a un entero . Se utiliza para
obtener parámetros de dirección, para comandos como PEEK.

47117 $ B80D PEEK


Perform PEEK

PEEK lee el parámetro de dirección y lo convierte en un puntero. Luego


, obtiene el byte apuntado al registro .Y y llama a la parte
de POS que convierte un único entero en .Y en un
número de coma flotante .

47140 $ B824 POKE


Perform POKE

POKE obtiene un puntero al parámetro de dirección y almacena el siguiente


parámetro allí.

47149 $ B82D FUWAIT


Realizar WAIT

WAIT obtiene un parámetro de dirección y un parámetro de número entero para usar como
máscara. WAIT luego busca un parámetro opcional para usar como patrón
para el OR exclusivo. Luego, se lee la ubicación de la dirección, su valor
se aplica en OR exclusivo con el valor del patrón opcional (o 0 si no hay
ninguno). Este valor está asociado con el valor de la máscara. El comando se repite
continuamente hasta que el resultado no es cero.

El propósito de este comando es permitir que el programa vea un


ubicación que puede ser cambiada por el sistema o por hardware externo
(como el reloj del software o ubicaciones de valores de códigos clave).

La función AND le permite verificar si un bit cambia de 0 a 1, mientras que


la función EOR le permite verificar si un bit cambia de 1 a 0.
Para obtener más información, consulte el artículo "Todo sobre la
instrucción de espera ", de Louis Sander y Doug Ferguson, en CÓMPUTO! 's primer
libro de Commodore 64.

47177 $ b849 FADDH


Añadir a 0.5 Contenido de punto flotante Acumulador # 1

47184 $ B850 FSUB


reste FAC1 de un número en la memoria

se utiliza esta rutina para restar el Punto flotante Acumulador de un


número en la memoria. Mueve el número en la memoria a FAC2 y pasa
a la siguiente rutina.

47187 $ B853 Operación


de resta de FSUBT BASIC

Esta rutina resta el contenido de FAC2 de FAC1 complementando


su signo y sumando.

47207 $ B867 FADD


Agregar FAC1 a un número en la memoria

Esta rutina se usa para agregar el contenido del


acumulador de punto flotante (FAC1) a un número en la memoria, moviendo ese número a
FAC2 y pasando a la siguiente rutina.

47210 $ B86A FADDT


Realizar la operación de adición de BASIC

Esta rutina agrega el contenido de FAC1 y FAC2 y almacena los resultados


en FAC1.

47271 $ B8A7 FADD4


Hacer que el resultado negativo Si un Borrow fue hecho

47358 $ B8FE NORMAL


Normalizar punto flotante Acumulador # 1

47431 $ B947 NEGFAC


Reemplazar FAC1 con su complemento a 2

47486 $ B97E overr


Imprimir desbordamiento mensaje de error

47491 $ B983 MULSHF


SHIFT rutina

47548 $ B9BC
Constante de punto flotante FONE con un valor de 1

Esta representación de punto flotante de cinco bytes del número 1 se almacena


aquí para que la utilicen las rutinas de punto flotante. También se utiliza como
valor STEP predeterminado para la instrucción FOR.

47553 $ B9C1 LOGCN2


www.unusedino.de/ec64/technical/project64/mapping_c64.html 56/126
25/9/2020 Mapping The C64
Tabla de constantes de coma flotante para la función LOG

Esta tabla de ocho constantes numéricas en


representación de coma flotante de cinco bytes es utilizada por la función LOG.

47594 $ B9EA LOG


Realizar LOG en Base E

El LOG en la base e del número en FAC1 se realiza aquí, y el


resultado se deja en FAC1.

47656 $ BA28 FMULT


Multiplica FAC1 con FAC2

Esta rutina multiplica el contenido de FAC1 por el contenido de FAC2


y almacena el resultado en FAC1

47705 $ BA59 MLTPLY


Multiplica una subrutina de bytes

Esta subrutina se usa para agregar repetidamente un byte de mantisa de FAC2 a


FAC1 el número de tiempos especificados en el registro .A.

47756 $ BA8C CONUPK


Mover un número de coma flotante de la memoria a FAC2

Esta subrutina carga FAC2 desde el número de cuatro bytes (tres mantisa
y un signo) señalado por los registros .A y .Y.

47799 $ BAB7 MULDIV


Suma el exponente de FAC1 al exponente de FAC2

47828 $ BAD4 MLDVEX Manejo de subdesbordamiento


o desbordamiento

47842 $ BAE2 MUL10


Multiplica FAC1 por 10

Esta subrutina se llama para ayudar a convertir un número de punto flotante en una
serie de números ASCII.

47865 $ BAF9 TENC


La constante 10 en formato flotante de cinco bytes

47870 $ BAFE DIV10


Divida FAC1 por 10

47887 $ BB0F FDIV


Divide un número en la memoria por FAC1

Este número en la memoria se almacena en FAC2, y esta rutina pasa


a la siguiente.

47890 $ BB12 FDIVT


Divide FAC2 por FAC1

Esta rutina se utiliza para dividir el contenido de FAC2 por el contenido de


FAC1, y el resultado se almacena en FAC1. Se comprueba la división entre 0
antes de dividir.

48034 $ BBA2 MOVFM


Mover un número de punto flotante de la memoria a FAC1

Esta rutina carga FAC1 con el número de punto flotante de cinco bytes
apuntado por la dirección almacenada en el acumulador (byte bajo) y el
registro .Y (byte alto).

48071 $ BBC7 MOV2F


Mover un número de punto flotante de FAC1 a la memoria

Esta rutina se utiliza para mover un número del


acumulador de punto flotante (FAC1) a la memoria en 92-96 ($ 5C- $ 60) o 87-91
($ 57- $ 5B), según en el punto de entrada a la rutina.

48124 $ BBFC MOVFA


Mover un número de punto flotante de FAC2 a FAC1

48140 $ BC0C MOVAF


Redondear y mover un número de punto flotante de FAC1 a FAC2

48143 $ BC0F MOVEF


Copiar FAC1 a FAC2 sin redondear

48155 $ BC1B ROUND


Acumulador de redondea # 1 ajustando el redondeo Byte

Si duplicar el byte de redondeo en la ubicación 112 ($ 70) lo hace mayor


que 128, el valor de FAC1 aumenta en 1.

48171 $ BC2B SIGN


Coloque el signo del acumulador # 1 en el registro .A

Al salir de esta rutina, el acumulador mantendrá un 0 si FAC1 es 0,


un 1 si es positivo y un valor de 255 ($ FF) si es negativo.

48185 $ BC39 SGN


Realizar SGN

www.unusedino.de/ec64/technical/project64/mapping_c64.html 57/126
25/9/2020 Mapping The C64
La rutina SGN llama a la rutina anterior para poner el signo de FAC1 en
.A, y luego convierte ese valor en un número de coma flotante en FAC1.

48216 $ BC58 ABS


Realizar ABS

El byte de signo FAC1 en 102 ($ 66) se desplaza a la derecha mediante este comando, de modo
que el bit superior es un 0 (positivo).

48219 $ BC5B FCOMP


Comparar FAC1 con la memoria

Al ingresar a esta rutina, .A y .Y apuntan a un


número de punto flotante de cinco bytes para compararlo con FAC1. Después de la comparación, .A tiene 0
si los dos son iguales, 1 si el valor de FAC1 es mayor que el de
la ubicación de memoria y 255 ($ FF) si el valor de FAC1 es menor
que el de la ubicación de memoria.

48283 $ BC9B QINT


Convertir FAC1 en entero dentro de FAC1

Esta rutina convierte el valor en FAC1 en un


entero de cuatro bytes con signo en 98-101 ($ 62- $ 65), con el byte más significativo primero.

48332 $ BCCC INT


Perform INT

Esta rutina elimina la parte fraccionaria de un número de punto flotante


llamando a la rutina anterior para cambiarla a un entero, y luego
cambiando el entero de nuevo al formato de punto flotante.

48371 $ BCF3 FIN


Convertir una cadena ASCII en un número de coma flotante FAC1

Esta rutina es llamada por VAL para evaluar y convertir una cadena ASCII
en un número de coma flotante.

48510 $ BD7E FINLOG


Agregar entero con signo a FAC1

Esta rutina se utiliza para agregar un dígito ASCII que se ha convertido en


un entero con signo a FAC1.

48563 $ BDB3 NO999

Esta tabla de tres constantes de coma flotante contiene los valores


99,999,999.5, 999,999,999.5 y 1,000,000,000. Estos valores se utilizan
para convertir cadenas en números de coma flotante.

48576 $ BDC0 INPRT


Imprimir ENTRADA seguida de un número de línea

48589 $ BDCD LINPRT Generar


un número en dígitos decimales ASCII

Esta rutina se usa para generar el número de línea para la rutina anterior.
Convierte el número cuyo byte alto está en .A y cuyo byte bajo está
en .X en un número de coma flotante. También llama a la rutina siguiente,
que convierte el número de punto flotante en una cadena ASCII.

48605 $ BDDD FOUT


Convertir el contenido de FAC1 en cadena ASCII

Esta rutina convierte un número de punto flotante en una cadena de


dígitos ASCII y establece un puntero a la cadena en .A y .Y.

48913 $ BF11 FHALF


El valor constante 1/2 en notación de coma flotante de cinco bytes

Esta constante se utiliza para redondeo y SQR.

48924 $ BF1C FOUTBL Tabla de


potencias de menos diez constantes

Esta tabla contiene las potencias de -10 expresadas como


números de coma flotante de cuatro bytes (es decir, -1; +10; -100; +1000; -10,000;
+100,000 ; -1,000,000 ; +10.000.000; y -100.000.000).

48954 $ BF3A FDCEND


Tabla de constantes para la conversión de TI $

Esta tabla contiene la representación en coma flotante de las potencias de


-60 multiplicadas por 1 o 10. Estas constantes se utilizan para convertir
TI $ a ASCII.

48978 $ BF52
Área no utilizada

Esta área no utilizada se llena con bytes de 170 ($ AA).

49009 $ BF71 SQR


Realizar SQR

Esta rutina mueve el contenido de FAC1 a FAC2, mueve la constante


0.5 a FAC1 y pasa a la rutina de exponenciación.

49019 $ BF7B FPWRT


Realiza exponenciación (cálculo de potencia solicitado por UPARROW)
www.unusedino.de/ec64/technical/project64/mapping_c64.html 58/126
25/9/2020 Mapping The C64

Esta rutina eleva el valor en FAC2 a la potencia en FAC1 y deja


el resultado en FAC1.

49076 $ BFB4 NEGOP


Ejecutar NOT y>

Esto niega el acumulador de punto flotante al aplicar un O exclusivo al


byte de signo con una constante de 255 ($ FF). El cero se deja sin cambios. Los
resultados de este comando siguen la fórmula NO X = - (X + 1).
Por lo tanto, si NO tiene una declaración que es verdadera (-1), obtiene 0 (falso).

49087 $ BFBF EXPCON


Tabla de constantes para EXP y LOG en formato de coma flotante de cinco bytes

Estas tablas se utilizan para calcular 2 elevado a la potencia N.

49133 $ BFED EXP


Ejecutar EXP

Esta rutina calcula el logaritmo natural e (2.718281828 ...)


elevado a la potencia en FAC1. El resultado se deja en FAC1.

Esta rutina se divide entre la ROM BÁSICA que termina en 49151 ($ BFFF)
y la ROM Kernal que comienza en 57344 ($ E000). Por lo tanto, se
agrega una instrucción JMP $ E000 al final, lo que hace que las
rutinas BASIC en la ROM de 64 núcleos tengan tres bytes más de memoria que las
correspondientes rutinas VIC-20.

49152-53247 $ C000- $ CFFF


4K RAM libre

Las ubicaciones 49152 a 53247 ($ C000 a $ CFFF) son RAM libre. Dado que esta
área no es contigua con el área de RAM del texto del programa BASIC, no está
disponible para el programa BASIC o el almacenamiento de variables (no se cuenta en
el total de FRE (0)).

Esta área está completamente disponible para cualquier otro uso, sin embargo, como
almacenar subrutinas de lenguaje de máquina para usar con BASIC,
controladores de E / S alternativos para dispositivos paralelos o IEEE, gráficos de caracteres o
datos de sprites , etc.

Esta gran área libre es tan tentadora lugar para adiciones al sistema que
muchas de estas aplicaciones pueden competir por el mismo espacio de RAM. Por
ejemplo, el programa Universal Wedge DOS Support que agrega un acceso fácil
al disco, el canal de comunicaciones generalmente se carga en 52224 ($ CC00).
Por tanto, los programas que utilizan esa parte de la RAM sobrescribirán el
programa de soporte de DOS , con el resultado de que es posible que no se ejecuten correctamente, o
incluso que no se ejecuten . Asimismo, Simon's BASIC, el lenguaje extendido que
Commodore ha lanzado en cartucho, utiliza varias ubicaciones en este
rango. Tenga en cuenta este problema potencial cuando compre accesorios de hardware
que utilicen este lugar para conectarse al sistema.

:::::::::::::::::::
:: Capítulo 6 ::
:: ::
:: VIC-II, SID, I / O ::
:: Dispositivos, Color ::
:: RAM y ::
:: ROM de caracteres ::
:::::::::::::::::::

53248-57343 $ D000- $ DFFF

Este bloque de memoria de 4K se utiliza para varias funciones clave. Normalmente,


el microprocesador 6510 trata aquí los dos
chips de entrada / salida del Adaptador de interfaz compleja (CIA), junto con el
chip controlador de video VIC-II , el sintetizador de música del Dispositivo de interfaz de sonido (SID) y la
RAM de color.

Alternativamente, el 6510 puede direccionar la ROM de caracteres aquí (aunque


normalmente solo el chip VIC-II tiene acceso a ella). Finalmente, también
hay 4K de RAM aquí, aunque para usarlo puede requerir almacenarlo solo
cuando sea necesario, ya que los dispositivos de E / S son necesarios para detalles como
leer el teclado y actualizar la pantalla.

Aparecerá en el mapa de los dispositivos de E / S a continuación que muchas de las


ubicaciones no se tienen en cuenta. Esto se debe a que estos dispositivos ocupan
más espacio de direccionamiento del que realmente utilizan. Cada uno de ellos usa solo
unas pocas direcciones, principalmente en el nivel de bits.

Las direcciones que faltan consisten en imágenes de los


registros de hardware o no se pueden direccionar en esta configuración. Además,
se deja un espacio de direcciones abierto para el uso de dispositivos de hardware futuros
que podrían conectarse al puerto de expansión, como la tarjeta CP / M.

Como se mencionó anteriormente, el uso de memoria de estos dispositivos de E / S es tan intensivo


que para trabajar con ellos a menudo es necesario activar bits individuales
y fuera. Aquí hay un recordatorio rápido de cómo manipular bits.

Los valores de bit para cada bit son:

Bit 0 = 1
Bit 1 = 2
Bit 2 = 4
Bit 3 = 8
www.unusedino.de/ec64/technical/project64/mapping_c64.html 59/126
25/9/2020 Mapping The C64
Bit 4 = 16
Bit 5 = 32
Bit 6 = 64
Bit 7 = 128

Para establecer un bit en 1 desde BASIC, POKE dirección, PEEK (dirección) O Bitvalue.
Para restablecer un bit a 0 desde BÁSICO, dirección POKE, PEEK (dirección) Y valor de
255 bits.

53248-53294 $ D000- $ D02E


Registros de chip VIC-II

El controlador de interfaz de video (chip VIC-II) es un


procesador especialmente diseñado que está a cargo de la pantalla de video del 64. Es este
chip el que hace posible la amplia gama de
capacidades gráficas del 64 .

La capacidad del chip VIC-II para direccionar la memoria es independiente del


microprocesador 6510 . Puede direccionar solo 16K a la vez, y cualquiera de los
cuatro bloques de 16K se puede elegir para la memoria de video. El sistema predeterminado
es que utilice los primeros 16K.

Toda la memoria de visualización de video, los datos de puntos de caracteres y las formas de sprites
deben almacenarse dentro del bloque de 16K elegido. Las ubicaciones 53248-53294
($ D000- $ D02E) son registros que permiten al usuario comunicarse con
el chip VIC-II. Aunque en su mayor parte se pueden escribir
y leer como ubicaciones de memoria ordinarias, su contenido
controla directamente la pantalla de video. Dado que muchas de estas ubicaciones funcionan en
estrecha colaboración con otras, una descripción general de algunas de las
diferentes sistemas gráficos en el 64 está en orden.

El tipo de pantalla gráfica más familiar es el texto ordinario que


aparece al encender la máquina. El área de RAM que se
muestra en la pantalla está determinada por la dirección base de la matriz de video
Nybble del registro de control de memoria VIC-II (53272, $ D018). La
dirección de los datos de puntos que se utiliza para asignar una forma a cada
carácter de texto en base a una matriz de 8 por 8 de puntos iluminados o no iluminados está determinada
por la otra mitad del Registro de control de memoria en 53272 ($ D018).
Puede encontrar más información sobre cómo se utilizan los datos para representar las
formas de los caracteres en la entrada alternativa de 49152 ($ C000), la
ROM del generador de caracteres.

Los gráficos de caracteres de texto pueden emplear uno de los dos conjuntos de
caracteres de texto y gráficos en la ROM del generador de caracteres, o el usuario puede
sustituir un conjunto de caracteres de texto o gráficos completamente diferente
en la RAM.

Normalmente, la pantalla de gráficos de texto utiliza un color de fondo que es


común a todos los caracteres de texto, y ese valor se almacena en el
Registro de color de fondo 0 (53281, $ D021). El color del marco alrededor de la
pantalla está determinado por el Registro de color del borde en 53280 ($ D020).

El color de cada carácter está determinado por un nybble de Color


RAM que comienza en 55296 ($ D800). Sin embargo, hay dos variaciones
que alteran un poco este esquema.

El primero se denomina modo de texto multicolor y se establece mediante el bit 4 de 53270


($ D016). En lugar de que cada bit seleccione el
color de primer plano o de fondo para cada punto del carácter, se utilizan pares de bits para
seleccionar uno de los cuatro colores para cada punto de doble ancho. Esto da como resultado que
la resolución horizontal se reduzca a cuatro puntos por carácter,
pero permite que se introduzcan dos colores adicionales desde los
registros de color de fondo 1 y 2 (53282-53283, $ D022- $ D023).

El otro modo de texto se llama Modo de color de fondo extendido. En este


modo, el color de primer plano siempre lo selecciona la RAM de color. El
color de fondo depende del código de pantalla real del personaje.
En este modo, solo están disponibles las primeras 64 formas de caracteres, pero
cada una puede tener uno de cuatro colores de fondo diferentes.

El color de fondo para cada carácter está determinado por su


código de pantalla de la siguiente manera:

1. Si el código de pantalla es de 0 a 63 (esto incluye los


alfanuméricos normales ), el valor en el Registro de color de fondo 0 (53281,
$ D021) determinará el color de fondo, como es habitual.

2. Los caracteres con códigos 64-255 tendrán la misma forma que el


carácter correspondiente en el grupo con códigos 0-63.

3. Para caracteres con códigos 64-127 (caracteres con MAYÚS), los


colores de fondo están determinados por el valor del
Registro de color de fondo 1 (53282, $ D022).

4. El valor en el Registro de color de fondo 2 (53283, $ D023) se usa


para caracteres con códigos 128-191 (alfanuméricos invertidos).

5. Para caracteres con códigos 192-255, el valor en el


Registro de color de fondo 3 (53284, $ D024) se usa para determinar el color de fondo.

En lugar del modo de texto normal, también está


disponible un modo de gráficos de mapa de bits configurando el Bit 5 de la ubicación 53265 ($ D011). En este modo,
cada bit de datos determina si un punto de la pantalla se establecerá
en el color de fondo o en el color de primer plano. Dentro de un área de 8 por 8
puntos, los colores de primer plano y de fondo pueden
seleccionarse individualmente .

www.unusedino.de/ec64/technical/project64/mapping_c64.html 60/126
25/9/2020 Mapping The C64
El área del mapa de bits tiene 320 puntos de ancho y 200 puntos de alto. El área que
contiene los datos gráficos, el mapa de bits, está determinado por la
dirección de base de datos de
puntos de caracteres en el nibble inferior del registro de control de memoria VIC-II (53272, $ D018). La dirección base de la matriz de video
nibble superior , que normalmente determina qué área de memoria se
mostrará, en cambio determina dónde se ubicará la memoria de color para cada 8 por 8
puntos.

La RAM de color no se utiliza para gráficos de mapa de bits de alta resolución. Pero el
modo multicolor también está disponible para gráficos de mapa de bits y utiliza la
RAM de color para determinar el color de primer plano de cada punto.

Al igual que con el modo de texto multicolor, la resolución horizontal es a la mitad


(hasta 160 puntos de ancho), de modo que, además del primer plano y
colores de fondo, cada punto puede ser uno de otros dos colores también.
Este modo obtiene el valor de los dos colores adicionales de los dos nybbles
de cada byte de la memoria de color de mapa de bits, cuya ubicación está
determinada por la dirección base de la matriz de video.

El modo de texto multicolor ofrece cuatro colores, tres de los cuales serán comunes
a todos los caracteres y uno de los cuales se puede seleccionar individualmente.
El modo de mapa de bits multicolor ofrece una selección de cuatro colores, tres de los cuales
se pueden seleccionar individualmente dentro de un área de 8 por 8 puntos.

El 64 también contiene un sistema de gráficos completamente separado, cuyas


formas, colores y posiciones de los personajes se derivan y se muestran
sin ninguna referencia a Video Matrix y Character Dot-Data.
direcciones. Lo mejor de todo es que estos personajes se pueden mover rápida y
fácilmente a cualquier posición de la pantalla, facilitando enormemente los juegos y
gráficos animados de todo tipo. Este sistema se conoce como
gráficos de sprites .

Los gráficos de Sprite toman su nombre de los caracteres gráficos que


muestra, cada uno de los cuales se denomina sprite. Hay ocho sprites,
conocidos como Sprites 0-7. Cada personaje de sprite tiene 24 puntos de ancho por 21
puntos de alto. Esto es aproximadamente ocho veces más grande que un
carácter de texto normal , que tiene solo 8 puntos de ancho por 8 puntos de alto.

Un sprite toma su forma a partir de 63 bytes de datos en uno de los 256


bloques de datos , cada uno de 64 bytes de largo, que puede caber en el espacio de 16K que el
El chip VIC-II puede abordar. El bloque asignado actualmente a cualquier objeto determinado
está determinado por los punteros de datos de Sprite, que se encuentran en
los últimos ocho bytes del área de memoria de la pantalla (las ubicaciones predeterminadas
son 2040-2047, $ 7F8- $ 7FF).

El primer puntero de datos de Sprite determina el bloque de datos utilizado para la


forma de Sprite 0, el segundo para la forma de Sprite 1, etc. El
número en el puntero multiplicado por 64 es igual a la dirección del primer byte del
bloque de datos dentro del VIC- II rango de direccionamiento.

Por ejemplo, usando los valores predeterminados para el área de direccionamiento VIC-II y
la memoria de pantalla, un valor de 11 en la ubicación 2040 ($ 7F8) significaría que
la forma de Sprite0 está determinada por los datos en el bloque de 63 bytes.
comenzando en la ubicación 704 (11 * 64). Cabe señalar que es
posible que más de un sprite tome sus datos de forma del mismo
bloque, de modo que solo se requieren 64 bytes de datos para crear ocho
sprites, cada uno con la misma forma.

Los patrones de puntos de cada sprite corresponden a los patrones de bits de los
datos de forma del sprite. Cada byte de datos de forma en la memoria consta de un
número del 0 al 255. Este número se puede representar con ocho
dígitos binarios de 0 o 1.

Cada dígito binario tiene un valor de bit que es dos veces mayor que el
anterior. Si el dígito en el lugar de bit cero es un 1, tiene un valor de 1
(contamos los lugares de bit de 0 a 7). Un 1 en el primer lugar de bit tiene un
valor de 2, el segundo bit tiene un valor de 4, el tercero tiene un valor de
8, el cuarto tiene un valor de 16, el quinto un valor de 32, el sexto un
valor de 64 y el séptimo un valor de 128 .

Al hacer todas las posibles combinaciones de 0 y 1. en las ocho


posiciones de bits, y la adición de los valores de los bits de cada lugar de bits que contiene
un 1, podemos representar todos los números del 0 al 255 como una serie de 1 de
y 0 de.

Si piensa en cada 0 como un punto que tiene el mismo color que el


fondo, y en cada 1 como un punto que es el color del sprite,
puede ver cómo se podría usar una serie de bytes para representar la
forma del sprite .

Dado que cada línea del objeto tiene 24 puntos de ancho, se necesitan 3 bytes de
memoria (24 bits) por línea para representar su forma. Echemos un vistazo a
un par de líneas de sprites de muestra.

00000000 01111110 00000000 = 0, 126, 0

Como puede ver, el primer y último bytes son todos 0, por lo que no se
mostrará nada allí. El byte del medio tiene seis unos, por lo que se
mostrará como una línea de seis puntos de longitud. Sumando los valores de estos
bits dix (64 + 32 + 16 + 8 + 4 + 2), obtenemos un valor de byte de 126. Probemos con otra
línea.

00011111 11111111 11111000 = 21, 255, 248

El primer byte tiene cinco bits establecidos en 1, con valores de 16, 8, 4, 2


y 1, para un total de 31. El segundo byte tiene todos los bits establecidos en 1, por lo que
tiene el valor máximo de 255. El tercer byte también tiene cinco bits
establecido en 1, con valores de 128, 64, 32, 16 y 8, para un total de 248.
www.unusedino.de/ec64/technical/project64/mapping_c64.html 61/126
25/9/2020 Mapping The C64
El resultado es que esta línea de datos de sprites mostrará una línea de
18 puntos de largo.

Podemos juntar estos dos tipos de líneas para mostrar cómo


se puede dibujar una cruz grande usando bytes de datos de sprites.

0000000000000000000000000000 = 0, 0, 0
000000000000000000000000 = 0, 0, 0
000000000111111000000000 = 0, 126, 0
000000000111111000000000 = 0, 126, 0
000000000111111000000000 = 0, 126, 0
000000000111111000000000 = 0, 126, 0
00000000011000 , 12611000000000 =
000000 = 0, 126, 0
000000000111111000000000 = 0, 126, 0
000111111111111111111000 = 21, 255, 248
000111111111111111111000 = 21, 255, 248
000111111111111111111000 = 21, 255, 248
000000000111111000000000 = 0, 126, 0
000000000111111000000000 = 0, 126, 0
000000000111111000000000 = 0, 126, 0
000000000111111000000000 = 0, 126, 0
000000000111111000000000 = 0, 126, 0
000000000111111000000000 = 0, 126, 0
000000000111111000000000 = 0, 126, 0
000000000000000000000000 = 0, 0, 0
000000000000000000000000 = 0,0,0

Los 63 números, mostrados tres por línea frente a los patrones de bits que
representan, son los valores que tendrían que ser poner en el
área de datos de forma de sprite para mostrar esta cruz usando gráficos de sprite.

Incluso después de que los datos de la forma del sprite se hayan colocado en la memoria, y el
puntero de datos
del sprite se haya configurado para mostrar ese bloque de bytes de datos como la forma del sprite, todavía hay varios pasos que se deben segui
para mostrar el sprite en la pantalla. .

El bit correcto del registro de habilitación de pantalla de Sprite en 53269 ($ D015)


debe establecerse en 1 para encender la pantalla de Sprite . Se
debe seleccionar una posición de pantalla horizontal y vertical para el sprite por medio
de los registros de posición horizontal y vertical (53248-53264,
$ D000- $ D010). Finalmente, el valor de color del sprite debe colocarse
en el Registro de color de Sprite apropiado (53287-53294, $ D027- $ D02E).

Una vez que tienes el objeto en la pantalla, la animación es bastante simple de


lograr. Mover el objeto es tan fácil como cambiar los valores en los
registros de posición del objeto. El cambio de la forma del sprite se puede
lograr simplemente cambiando el puntero de datos del sprite para que apunte a
otro bloque de datos de forma en la memoria.

También hay algunas características de gráficos de sprites opcionales disponibles que


mejoran su flexibilidad. Los registros de expansión de
sprites te permiten hacer que cada sprite sea el doble de ancho de lo normal, el doble de alto o ambos.
Los registros de detección de colisiones te permiten saber cuando la forma de
un objeto se superpone a un carácter de texto normal o un punto de mapa de bits, o si dos objetos se
tocan.

Si un objeto se coloca en el mismo lugar de la pantalla que un


carácter de texto o un punto de mapa de bits, un Registro de prioridad le permite elegir
si se mostrará el objeto o los gráficos normales. Esto
habilita efectos tridimensionales permitiéndole elegir si el objeto
va delante o detrás de otros objetos en la pantalla.

Por último, se puede seleccionar cualquier objeto para visualización multicolor, utilizando el
registro en la ubicación 53276 ($ D01C). En este modo, como en los
modos de texto multicolor y mapa de bits, se utilizan pares de bits para determinar el color
de cada punto de doble ancho. Los posibles valores de color que pueden
seleccionarse son los del Registro de color de fondo 0, el Color de Sprite
Regístrese, o los dos valores de color en los Registros Sprite Multicolor
en 53285-53286 ($ D025- $ D026).

Rango de ubicación: 53248-53264 ($ D000- $ D010)


Registros de posición horizontal y vertical de Sprite

Estas ubicaciones determinan la posición horizontal y vertical en la


que se mostrará cada objeto en la pantalla. Cada objeto tiene
su propio registro de posición horizontal y vertical. Además, todos
los sprites comparten un registro común que se utiliza para ampliar el
rango de posiciones horizontales.

Las posiciones verticales para cada sprite van de 0 a 255, y estas


indican la posición vertical de la línea superior de la
longitud de 21 líneas del sprite . Dado que solo hay 200 líneas de escaneo visibles en la pantalla
pantalla, algunas de estas posiciones verticales darán como resultado que el sprite
esté parcial o totalmente fuera de la pantalla.

El área de visualización visible comienza en la línea 50 y se extiende hasta la línea 249.


Por lo tanto, cualquier objeto cuya posición vertical sea 29 ($ 1D) o menos estará
completamente por encima de la imagen visible. En la posición vertical 30
($ 1E), la línea inferior de la pantalla del sprite se vuelve visible en la
parte superior de la pantalla. En la posición 230 ($ E6), la línea inferior del
sprite se pierde de la vista desde la parte inferior de la pantalla, y en la
posición vertical 250 ($ FA), todo el sprite desaparece de la vista desde el
borde inferior de la pantalla.

El posicionamiento horizontal es algo más complicado, porque el visible


El área de visualización tiene 320 puntos de ancho y un registro de ocho bits puede contener
solo 256 valores de posición. Por lo tanto, se necesita un registro adicional
www.unusedino.de/ec64/technical/project64/mapping_c64.html 62/126
25/9/2020 Mapping The C64
para mantener el noveno bit de la posición horizontal de cada objeto.

A cada sprite se le asigna un solo bit en el registro de bit más significativo de


posición horizontal (registro MSB) en 53264 ($ D010). Si ese
bit se establece en 1, el valor 256 se agrega a la posición horizontal.
Esto extiende el rango de posibles posiciones horizontales a 511.

Para establecer la posición horizontal de un objeto, debes asegurarte de


que tanto los valores en el registro de posición horizontal como en el
Registro MSB sean correctos. Por ejemplo, si desea establecer la horizontal
posición del Sprite 5 a un valor de 30, debe colocar un valor de 30 en
el Registro de Posición Horizontal del Sprite 5 (POKE 53258,30 lo hará
desde BÁSICO), y también debe borrar el Bit 5 del Registro MSB (POKE
53264 , PEEK (53264) Y (255-16)). Si olvida el registro MSB y el
bit 5 se establece en 1, terminará en la posición 286 en lugar de 30.

El valor de la posición horizontal indica la posición del


punto más a la izquierda del ancho de 24 puntos del sprite. La pantalla visible está restringida
a las posiciones de 320 puntos entre las posiciones 24 y 344. En la posición 0,
todo el sprite pasa por el borde izquierdo de la pantalla visible. En la
posición 1, el punto más a la derecha ingresa al área de visualización, y en la posición
24 ($ 18) el sprite completo se muestra en la pantalla. En la posición 321
($ 141), el punto más a la derecha pasa el borde derecho del
área de visualización visible , y en la posición 355 ($ 158) todo el sprite se ha movido fuera
de la vista, fuera del borde derecho de la pantalla.

Todos estos registros se inicializan a 0 en el momento del encendido.

53248 $ D000 SP0X


Sprite 0 Posición horizontal

53249 $ D001 SP0Y


Sprite 0 Posición vertical

53250 $ D002 SP1X


Sprite 1 Posición horizontal

53251 $ D003 SP1Y


Sprite 1 Posición vertical

53252 $ D004 SP2X


Sprite 2 Posición horizontal

53253 $ D005 SP2Y


Sprite 2 Posición vertical

53254 $ D006 SP3X


Sprite 3 Posición horizontal

53255 $ D007 SP3Y


Sprite 3 Posición vertical

53256 $ D008 SP4X


Sprite 4 Posición horizontal

53257 $ D009 SP4Y


Sprite 4 Posición vertical

53258 $ D00A SP5X


Sprite 5 Posición horizontal

53259 $ D00B SP5Y


Sprite 5 Posición vertical

53260 $ D00C SP6X


Sprite 6 Posición horizontal

53261 $ D00D SP6Y


Sprite 6 Posición vertical

53262 $ D00E SP7X


Sprite 7 Posición horizontal

53263 $ D00F SP7Y


Sprite 7 Posición vertical

53264 $ D010 MSIGX


Bits más significativos de Sprites 0-7 Posición horizontal

Bit 0: Bit más significativo de la posición horizontal Sprite 0


Bit 1: Bit más significativo de la posición horizontal Sprite 1
Bit 2: Bit más significativo de la posición horizontal del Sprite 2
Bit 3: Bit más significativo de la posición horizontal del Sprite 3
Bit 4: Bit más significativo de la posición horizontal del Sprite 4
Bit 5: Bit más significativo de la posición horizontal del Sprite 5
Bit 6: Bit más significativo de la posición horizontal del Sprite 6
Bit 7: Bit más significativo de la posición horizontal de Sprite 7

Establecer uno de estos mordiscos en 1 agrega 256 a la posición horizontal del


sprite correspondiente. Restablecer uno de estos bits a 0 restringe
la posición horizontal del sprite correspondiente a un valor de 255
o menos

53265 $ D011 SCROLY


Desplazamiento fino vertical y registro de control

Bits 0-2: visualización de desplazamiento fino verticalmente por X líneas de exploración (0-7)
Bit 3: seleccione una pantalla de texto de 24 o 25 filas (1 = 25 filas, 0 = 24 filas)
www.unusedino.de/ec64/technical/project64/mapping_c64.html 63/126
25/9/2020 Mapping The C64
Bit 4: En blanco toda la pantalla con el mismo color que el fondo
(0 = en blanco)
Bit 5: Habilitar gráficos de mapa de bits modo (1 = habilitar)
Bit 6: habilitar el modo de texto en color extendido (1 = habilitar)
Bit 7: Bit alto (Bit 8) del registro de comparación de ráster en 53266 ($ D012)

Este es uno de los dos importantes registros de control multifunción en


el chip VIC-II. Su valor predeterminado es 155, que establece el bit alto del
ráster en comparación con 1, selecciona una pantalla de 25 filas, desactiva la
función de supresión y utiliza un desplazamiento de desplazamiento vertical de tres
líneas de exploración .

Bits 0-2. Estos bits controlan el desplazamiento vertical fino de la pantalla


. Esta función le permite mover la pantalla completa de texto
suavemente hacia arriba y hacia abajo, permitiendo que el área de visualización actúe como una ventana,
desplazándose sobre una pantalla de texto o gráficos de caracteres más grande.

Dado que cada fila de texto tiene una altura de ocho líneas de escaneo, si simplemente mueve
cada línea de texto una fila hacia arriba, los caracteres se desplazan considerablemente.
distancia cada vez que se mueven, lo que le da al movimiento una cualidad entrecortada.
A esto se le llama desplazamiento
aproximado , y puede ver un ejemplo de ello al LISTAR un programa que es demasiado largo para caber en la pantalla todo a la
vez.

Al colocar un número del 1 al 7 en estos tres bits, puede mover


toda la pantalla hacia abajo de 1 a 7 espacios de puntos. Pasar
por los valores del 1 al 7 le permite realizar sin problemas la transición
de que un personaje aparezca en una fila en la pantalla a que
aparezca en la siguiente fila. Para demostrar esto, escriba el siguiente
programa de ejemplo, LISTA y EJECUTE.

10 PARA I = 1 A 50: PARA J = 0 A 7


20 POKE 53265, (PEEK (53265) AND248) O J: NEXTJ, I
30 FOR I = 1 TO 50: FOR J = 7 TO 0 STEP-1
40 POKE 53265, (PEEK (53265) AND248) OR J: NEXTJ, I

Como puede ver, después de que la pantalla se haya movido siete posiciones de puntos hacia arriba o
hacia abajo , comienza de nuevo en su posición original. Para continuar
el desplazamiento, debe realizar un desplazamiento aproximado cada vez que el valor de los
bits de desplazamiento va de 7 a 0, o de 0 a 7. Esto se logra
moviendo los datos de la pantalla para cada línea en 40 bytes en cualquier dirección ,
sobrescribiendo los datos de la última línea e introduciendo una línea de datos
en el extremo opuesto de la memoria de pantalla para reemplazarla. Obviamente, solo un
programa en lenguaje de máquina puede mover todas estas líneas lo suficientemente rápido como para
mantener el efecto de movimiento suave. El siguiente programa BÁSICO,
sin embargo, le dará una idea de cómo es el desplazamiento vertical fino:

10 POKE 53281,0: PRINTCHR $ (5); CHR $ (147)


20 FORI = 1 TO 27:
30 PRINTTAB (15) CHR $ (145) " ": POKE 53265, PEEK (53265) AND248
40 WAIT53265,128: PRINTTAB (15)" ME CAYO "
50 PARA J = 1 A 7
60 POKE53265, (PEEK (53265) AND248) + J
70 HORQUILLA = 1TO50
80 SIGUIENTE K, J, I: RUN

Bit 3. Este registro de bits le permite seleccionar la


visualización de texto normal de 25 líneas (estableciendo el bit en 1) o una
visualización abreviada de 24 filas (restableciendo ese bit a 0). Esta visualización abreviada se
crea extendiendo el borde para superponer la fila superior o inferior. Los
personajes de estas filas todavía están allí; simplemente están cubiertos.

La pantalla acortada está diseñada para facilitar el desplazamiento vertical fino. Se


cubre hasta la línea en la que se introduce nuevos datos de pantalla, para que
el espectador no ve los nuevos datos que se mueven en su lugar.

Sin embargo, desvincule el registro en 53270 ($ D016), lo que acorta la


pantalla en un espacio de un carácter a cada lado para ayudar al
desplazamiento horizontal en cualquier dirección, este registro puede dejar en blanco solo una
línea vertical a la vez. Para compensar, deja en blanco la
línea superior cuando los tres bits de desplazamiento en este registro se establecen en 0, y
desplaza el borrado una línea de exploración a la vez a medida que
aumenta el valor de los tres bits . Por lo tanto, la línea de fondo está totalmente en blanco cuando estos bits
se establecen en 7.

Bit 4. El bit 4 de este registro controla la función de supresión de pantalla.


Cuando este bit se establece en 0, no se pueden mostrar datos en la pantalla.
En su lugar, toda la pantalla se rellenará con el color del marco
(que está controlado por el Registro de colores de eBorder en 53280 ($ D020)).

El borrado de pantalla es útil debido a la forma en que el chip VIC-II


interactúa con el microprocesador 6510. Dado que el VIC-II y el 6510
tienen que direccionar la misma memoria, deben compartir el
bus de datos del sistema . Compartir el bus de datos significa que deben turnarse siempre
que quieran direccionar la memoria.

El chip VIC-II fue diseñado para que obtenga la mayoría de los datos que
necesidades durante la parte del ciclo en la que el 6510 no está utilizando el
bus de datos. Pero ciertas operaciones, como leer los 40 códigos de pantalla
necesarios para cada línea de texto de la memoria de video, o buscar
datos de sprites , requieren que el chip VIC-II obtenga datos a un ritmo más rápido de lo que es
posible usando la mitad de la 6510 ciclo.

Por lo tanto, el chip VIC-II debe retrasar el 6510 durante un corto período de tiempo
mientras está usando el bus de datos para recopilar información de visualización para texto
o gráficos de mapa de bits, y debe retrasarlo un poco más si los sprites
también están habilitados. Cuando establece el bit de supresión de pantalla en 0, estos retrasos
se eliminan y el procesador 6510 puede funcionar a su máxima potencia.
www.unusedino.de/ec64/technical/project64/mapping_c64.html 64/126
25/9/2020 Mapping The C64
velocidad. Esto acelera un poco cualquier tarea de procesamiento.

Para demostrar esto, ejecute el siguiente programa corto. Como


verá, dejar la pantalla encendida hace que el procesador funcione aproximadamente un 7 por ciento
más lento que cuando lo apaga. Si realiza la misma prueba de sincronización
en el VIC-20, encontrará que funciona a la misma velocidad con la
pantalla encendida que el 64 con la pantalla apagada. Y la misma prueba en un
PET se ejecutará sustancialmente más lento.

10 PRINT CHR $ (147); TAB (13); "TIMING TEST": PRINT: TI $ = "000000": GOTO 30
20 FOR I = 1 TO 10000: NEXT I: RETURN
30 GOSUB 20: DISPLAY = TI
40 POKE 53265,11: TI $ = "000000"
50 GOSUB 20: NOSCREEN = TI: POKE 53265,27
60 PRINT "THE LOOP TOOK"; DISPLAY; "
70 IMPRIMIR "SIN PANTALLA EN BLANCO": IMPRIMIR
80 IMPRIMIR "EL LAZO SE HIZO"; PANTALLA MÓVIL; "JIFFIES"
90 IMPRIMIR "CON PANTALLA EN BLANCO": IMPRIMIR
100 IMPRIMIR "PANTALLA EN BLANCO HACER QUE EL PROCESADOR"
110 IMPRIMA "VAYA"; PANTALLA / PANTALLA NOSOTROSA * 100-100; "POR CIENTO MÁS RÁPIDO"

La explicación anterior explica que la pantalla se apaga durante


las operaciones de lectura y escritura de la cinta. La sincronización de estas operaciones es
bastante crítica y se vería afectada incluso por el
retardo relativamente pequeño causado por el chip de video. También explica por qué el 64 tiene
dificultades para cargar programas desde una unidad de disco 1540 sin modificar, ya que
el 1540 se configuró para transferir datos desde el VIC-20,

Si apaga la pantalla 64 con un POKE 53265, PEEEK (53265) Y 239,


podrá cargar programas correctamente desde una unidad 1540 antigua.
La nueva unidad 1541 transfiere datos a una velocidad ligeramente más lenta en la
configuración predeterminada y se puede configurar desde el software para transferirlos a
una velocidad más alta para el VIC-20.

Bit 5. Establecer el Bit 5 de este registro en 1 habilita el


modo de gráficos de mapa de bits . En este modo, el área de la pantalla se divide en
64.000 puntos de luz separados, 320 puntos de ancho por 200 puntos de alto. Cada
punto corresponde a un bit de memoria de pantalla. Si el bit se establece en 1,
el punto se mostrará en el color de primer plano. Si el bit se
restablece a 0, se mostrará en el color de fondo. Esto permite
la visualización de imágenes gráficas de alta resolución para juegos, cuadros y
gráficos, etc. El

mapa de bits es una técnica común para implementar


gráficos de alta resolución en una microcomputadora. Sin
embargo, hay algunas características del sistema Commodore que son inusuales.

La mayoría de los sistemas muestran la memoria de la pantalla de forma secuencial; es decir, el primer
byte controla la visualización de los primeros ocho puntos en la
esquina superior izquierda de la pantalla, el segundo byte controla los ocho puntos a la
derecha de eso, etc. En el sistema Commodore, la memoria de visualización se distribuye
más siguiendo las líneas de cómo se
organizan los datos de puntos de los gráficos de caracteres .

El primer byte controla la fila de ocho puntos en la esquina superior izquierda


de la pantalla, pero el siguiente byte controla los ocho puntos debajo de eso,
y así sucesivamente hasta el noveno byte. El noveno byte controla los ocho
puntos directamente a la derecha de los controlados por el primer byte de la
memoria de pantalla. Es exactamente lo mismo que si la pantalla estuviera llena
de 1000 caracteres programables, con la memoria de visualización tomando el
lugar de los datos de puntos de carácter.

El modo de gráficos de mapa de bits del 64 también se parece a los gráficos de caracteres en
que el color de primer plano de los puntos se establece mediante un mapa de color (aunque
no utiliza la RAM de color para este propósito). Cuatro bits de cada
byte de esta memoria de color controlan el color de primer plano de uno de estos
grupos de ocho bytes de memoria de pantalla (que forman una cuadrícula de 8 por 8 de 64
puntos). Sin embargo, a diferencia de los gráficos de caracteres, los otros cuatro bits
controlan el color de fondo que se verá en el
grupo de visualización de ocho bytes donde un bit tiene un valor de 0.

Configurar una pantalla de gráficos de mapa de bits es algo más complicado que
simplemente configurar este bit de registro a 1. Primero debe elegir una ubicación
para el área de memoria de pantalla y para el área de memoria de color. El
área de memoria de la pantalla tendrá una longitud de 8192 bytes (8000 de los cuales se
utilizan en realidad para la pantalla) y puede ocupar solo la primera o la
segunda mitad del espacio de 16K que puede abordar el chip VIC-II.

Cada byte de la memoria de color de gráficos de mapa de bits utiliza cuatro bits para el
color de fondo y cuatro bits para el color de primer plano.
Por lo tanto, los nibbles de Color RAM en 55296 ($ D800), que están cableados solo para
cuatro bits, no se pueden usar. Por lo tanto, se
debe encontrar otra ubicación de RAM para la memoria de color.

Esta área de memoria de color ocupará 1K (1000 bytes de los cuales se


utilizan en realidad para controlar los colores de primer plano y de fondo de los
puntos) y debe estar en la mitad opuesta de la memoria VIC-II como
datos de visualización. Dado que los gráficos de mapa de bits requieren tanta memoria para la
pantalla, es posible que desee seleccionar un banco de 16K diferente para la memoria VIC-II
(consulte la discusión sobre los aspectos a considerar al seleccionar un
banco de memoria VIC-II en la ubicación 56576 ($ DD00)).

Sin embargo, para simplificar las cosas, supongamos que ha seleccionado


utilice el banco predeterminado de memoria VIC-II, que es el primer 16K. Usted
tendría que seleccionar ubicaciones 8192-16383 ($ 2000- $ 3FFF) para la pantalla de
la memoria, ya que el chip VIC-II ve una imagen de la ROM de caracteres en
la primera mitad del bloque de 16K (en ubicaciones 4096-8192
($ 1000- $ 1 FFF)). La memoria de color se puede colocar en la ubicación predeterminada
www.unusedino.de/ec64/technical/project64/mapping_c64.html 65/126
25/9/2020 Mapping The C64
de la memoria de visualización de texto, en 1024-2047 ($ 400- $ 7FF). La ubicación de la
pantalla de mapa de bits y la memoria de color está controlada por el Registro de control de memoria VIC
en 53272 ($ D018).

Cuando está en modo de mapa de bits, los cuatro bits inferiores de este registro, que
normalmente controlan la dirección base de los datos de puntos de carácter, ahora controlan
la ubicación del mapa de bits de 8K. Solo el bit 3 es significativo. Si esto es
Si se establece en 1, la memoria de visualización de gráficos estará en los segundos 8K de la
memoria VIC-II (en este caso, a partir de 8192 ($ 2000)). Si ese bit
contiene un 0, los primeros 8K se utilizarán para el mapa de bits. Los
cuatro bits superiores de este registro, que normalmente controlan la ubicación de la
matriz de visualización de video, se utilizan en modo de mapa de bits para establecer la
ubicación del mapa de color dentro del espacio de direcciones VIC-II. Estos cuatro
bits pueden contener un número de 0 a 15, que indica en qué
límite de 1K comienza el mapa de color. Por ejemplo, si la memoria de color comienza en
1024 (1K), el valor de estos cuatro bits sería 0001.

Una vez que se ha seleccionado el modo de mapa de bits, y la pantalla y el color


áreas de memoria configuradas, debe establecer un método para encender y apagar cada
punto individual. El método convencional para identificar
cada punto es asignarlo a una coordenada de posición horizontal (X) y una coordenada
vertical (Y).

Los valores de la posición horizontal oscilarán entre 0 y 319, donde el punto 0 está en
el extremo izquierdo de la pantalla y el punto 319 en el extremo
derecho. Las posiciones verticales oscilarán entre 0 y 199, donde el punto 0 está en
la línea superior y el punto 199 está en la línea inferior.

Debido al diseño inusual de los datos de la pantalla de mapa de bits en el 64, es


bastante fácil transferir caracteres de texto a una pantalla de mapa de bits, pero es
un poco incómodo encontrar el bit que afecta al punto de la pantalla que tiene un
dada la coordenada XY. Primero, debe encontrar el byte BY en el que
reside el bit, y luego debe insertar un valor en ese byte que activa
o desactiva el bit deseado. Dado que la posición horizontal del
punto está almacenada en la variable X, su posición vertical está en la
variable Y, y la dirección base del área del mapa de bits está en la variable
BASE, puede encontrar el byte deseado con la fórmula:

BY = BASE + 40 * (Y Y 256) + (Y Y 7) + (X Y 504)

Para activar el punto deseado,

PULSE POR, ESCUCHE (POR) O (2 ^ (NOTX Y 7)

Para apagar el punto,

POKE BY, PEEK (BY) AND (255-2 ^ (NOTX AND 7))

La función de exponenciación lleva mucho tiempo. Para acelerar las cosas,


se puede crear una matriz, cada uno de cuyos elementos corresponde a una potencia
de dos.

PARA I = 0 A 7: BIT (I) = 2 ^ 1: NEXT

Una vez hecho esto, la expresión 2 ^ (I) se puede reemplazar por BI (I).

El siguiente programa de muestra ilustra los conceptos de gráficos de bits


explicados anteriormente y sirve como resumen de esa información.

10 PARA I = 0 A 7: BI (I) = 2 ^ I: SIGUIENTE: CONFIGURACIÓN REM ARRAY DE PODERES DE 2 (VALOR DE BIT)


20 BASE = 2 * 4096: POKE53272, PEEK (53272) OR8: REM PUT BIT MAP AT 8192
30 POKE53265, PEEK (53265) OR32: REM ENTER BIT MAP MODE
40 A $ = "": PARA I = 1 A 37: A $ = A $ + "C": SIGUIENTE: IMPRIMIR CHR $ (19);
50 FOR I = 1 TO 27: PRINTA $ ;: NEXT: POKE2023, PEEK (2022): REM SET COLOR MAP
60 A $ = "": FOR I = 1 TO 27: A $ = A $ + "@": NEXT : PARA I = 32 A 63 PASO 2
70 POKE648, I: PRINT CHR $ (19); A $; A $; A $; A $: SIGUIENTE: POKE648,4: REM CLEAR HI-RES SCREEN
80 FORY = 0TO199STEP.5: REM DESDE LA PARTE SUPERIOR DE LA PANTALLA HACIA ABAJO
90 X = INT (160 + 40 * SIN (Y / 10)): FORMA
DE ONDA SINusoidal REM 100 BY = BASE + 40 * (Y Y 248) + (Y Y 7) + (X Y 504): REM ENCONTRAR HI-RES BYTE
110 POKEBY, PEEK (BY) O (BI (NOT X AND 7)): NEXT Y: REM POKE IN BIT VALUE
120 GOTO 120: REM DEJARLO EN LA PANTALLA

Como puede ver, usando BASIC para dibujar en el modo de gráficos de bits es algo
lento y tedioso. El lenguaje de máquina es mucho más adecuado para el
trazado de gráficos de bits. Para ver un programa que le permite reemplazar algunos
comandos BÁSICOS con comandos de dibujo de alta resolución, consulte el artículo "
Gráficos de alta resolución simplificados ", de Paul F. Schatz, en el primer libro de COMPUTE!
Sonido y gráficos de Commodore 64.

Hay un modo de gráficos de mapa de bits de resolución ligeramente inferior disponible


que ofrece hasta cuatro colores por matriz de puntos de 8 por 8. Para habilitar este
modo, debe configurar el bit multicolor (Bit 4 de 53270 ($ D016)) mientras se encuentra
en el modo de gráficos de mapa de bits. Para obtener más información sobre este modo, consulte la
entrada del bit de habilitación multicolor.

Bit 6. Este bit de este registro habilita el


modo de color de fondo extendido . Este modo le permite seleccionar el color de fondo de cada
carácter de texto , así como su color de primer plano. Puede aumentar
la cantidad de colores de fondo mostrados, reduciendo la cantidad de
caracteres que se pueden mostrar en la pantalla.

Normalmente, se pueden mostrar 256 formas de caracteres en la pantalla. Puede


utilizarlos utilizando la instrucción PRINT o introduciendo un
código de visualización de 0 a 255 en la memoria de pantalla. Si se utiliza el método POKEing
, también debe introducir un código de color del 0 al 15 en la
memoria de colores (por ejemplo, si POKE 1024,1 y POKE 55296,1,
aparece una A blanca en la esquina superior izquierda del pantalla).

www.unusedino.de/ec64/technical/project64/mapping_c64.html 66/126
25/9/2020 Mapping The C64
El color de fondo de la pantalla está determinado por el
Registro de color de fondo 0, y puede cambiar este color introduciendo un nuevo valor en
ese registro, que se encuentra en 53281 ($ D021). Por ejemplo, POKE
53281,0 crea un fondo negro.

Sin embargo, cuando se activa el modo de color de fondo extendido,


Las primeras 64 formas que se encuentran en la tabla de códigos de visualización de pantalla se pueden
mostrar en la pantalla. Este grupo incluye las letras del
alfabeto, números y signos de puntuación. Si intenta imprimir en la
pantalla un carácter que tiene un código de visualización más alto, la forma mostrada
será del primer grupo de 64, pero el fondo de ese carácter
ya no será determinado por el registro en 53281 ($ D021).
En cambio, será determinado por uno de los otros
registros de color de fondo .

En el modo de color de fondo extendido, los caracteres que tienen


códigos de visualización 64-127 tomarán su color de fondo del registro 1 y la
ubicación 53282 ($ D022). Estos personajes incluyen varios SHIFTed
caracteres. Aquellos con códigos 128-191 tendrán sus
colores de fondo determinados por el registro 2, en 53283 ($ D023). Estos incluyen los
números, letras y signos de puntuación invertidos. Finalmente, los caracteres
con códigos 192-255 usarán el registro 4, en 53284 ($ D024). Estos son
los personajes gráficos invertidos.

Intentemos un experimento para ver cómo funciona esto. Primero, pondremos


los códigos para cuatro letras diferentes en la memoria de la pantalla:

FOR I = 0 TO 3: POKE 1230+ (I * 8), I * 64 + I: POKE 55502+ (I * 8), 1: NEXT

Four Deben aparecer letras blancas en la pantalla, una A, una A desplazada, una
A invertida y una A invertida y desplazada, todo sobre un fondo azul.
A continuación, pondremos colores en los otros registros de color de fondo:

POKE 53282,0: POKE53283,2: POKE53284,5

Esto establece los registros en negro, rojo y verde, respectivamente.


Finalmente, activaremos el modo de color extendido configurando el Bit 6 del
registro VIC-II en la ubicación 53265 en 1. La declaración BASIC que
activa este modo es:

POKE 53265, PEEK (53265) OR 64

Observe que sucedieron dos cosas. Primero, todas las letras tomaron
la misma forma, la de la letra A. En segundo lugar, cada una tomó el
color de fondo de un registro de color diferente. Para que todo vuelva a la
normalidad, desactive el modo de color extendido con esta declaración:

POKE 53265, PEEK (53265) Y 191

El modo de color extendido puede ser una mejora muy útil para su texto
muestra. Permite la creación de ventanas. Estas ventanas, debido
a sus diferentes colores de fondo, hacen que diferentes cuerpos de texto se
destaquen como visualmente distintos entre sí. Por ejemplo, un
programa de aventuras de texto podría tener una ventana para mostrar la
ubicación actual del jugador , una para mostrar un inventario de posesiones y otra para
aceptar órdenes para el próximo movimiento.

En este modo, el color de fondo de estas ventanas se puede cambiar


instantáneamente, simplemente introduciendo un nuevo valor en el registro de color. Esta
técnica se presta a algunos efectos dramáticos. Se puede
mostrar una ventana para llamar la atención sobre un mensaje en particular en determinados momentos.
Y variar el color de primer plano puede hacer que la ventana o el
El mensaje desaparece y reaparece más tarde.

Sin embargo, existen algunos problemas relacionados con el uso de estas


ventanas. Es posible que la forma de carácter que desee utilizar no tenga un
código de pantalla inferior a 64. En ese caso, la única solución es
definir su propio conjunto de caracteres, con la forma que desee en uno de los
primeros 64 caracteres.

Otro problema es que los caracteres dentro de una instrucción PRINT en su


lista de programas no siempre tendrán el mismo aspecto en la pantalla.
Tener que averiguar qué letra imprimir para obtener el número 4 con un
color de fondo determinado puede ser muy inconveniente. La
solución más sencilla a este problema es tener una subrutina para la traducción
para ti. Dado que las letras aparecerán normalmente en la ventana 1, y los
caracteres de la ventana 3 son simplemente los caracteres de la ventana 1 invertidos, solo tendrá
problemas con los caracteres en las ventanas 2 y 4. Para convertir estos
caracteres, coloque su mensaje en A $ y use la siguiente subrutina :

500 B $ = "": PARA I = 1 HASTA LEN (A $): B = ASC (MID $ (A $, I, 1))


510 B = B + 32: SI B <96 ENTONCES B = B + 96
520 B $ = B $ + CHR $ (B): SIGUIENTE I: RETORNO

Esta subrutina convierte cada letra en su equivalente ASCII, agrega el


desplazamiento adecuado y la convierte nuevamente en parte de la nueva cadena, B $.
Cuando se complete la conversión, B $ contendrá los caracteres necesarios
para IMPRIMIR ese mensaje en la ventana 2. Para la ventana 4, IMPRIMIR
CHR $ (18); B $; CHR $ (146). Esto activará el vídeo inverso antes de
imprimir la cadena y lo desactivará después.

En
el programa de muestra siguiente se ofrece una demostración práctica de la técnica para configurar ventanas . El programa configura tres venta
y las muestra parpadeando, apareciendo y desapareciendo.

5 DIM RO $ (25): RO $ (0) = CHR $ (19): FOR I = 1 TO 24: RO $ (I) = RO $ (I-1) + CHR $ (17): SIGUIENTES
10 POKE 53265, PEEK (53265) OR 64
20 POKE 53280,0: POKE 53281,0: POKE 53282,1: POKE 53283,2: POKE 53284,13
www.unusedino.de/ec64/technical/project64/mapping_c64.html 67/126
25/9/2020 Mapping The C64
25 OP $ = CHR $ (160): PARA I = 1 A 4: OP $ = OP $: NEXTI: PRINTCHR $ (147); RO $ (3);
30 FOR I = 1 TO10: PRINTTAB (1); CHR $ (18); ""; TAB (23); OP $: SIGUIENTE
40 PRINT CHR $ (146): PRINT: PRINT: FOR I = 1 TO 4: PRINTOP $; OP $; OP $; OP $; OP $ ;: NEXTI
50 PRINT RO $ (5); CHR $ (5); CHR $ (18); TAB (2); "UNA VENTANA ROJA"
60 PRINT CHR $ (18); TAB (2); "PODRÍA UTILIZARSE"
70 PRINT CHR $ (18); TAB (2); "PARA ERROR"
80 PRINT CHR $ (18); TAB (2); "MESSAGES"
100 A $ = "UNA VENTANA VERDE": GOSUB 300: PRINT RO $ (5) ; CHR $ (144); CHR $ (18); TAB (24); B $
110 A $ = "SE PUEDE UTILIZAR": GOSUB 300: PRINTTAB (24); CHR $ (18); B $
120 A $ = "PARA DAR": GOSUB 300: PRINTTAB (24); CHR $ (18); B $
130 A $ = "INSTRUCCIONES": GOSUB 300: PRINTTAB (24); CHR $ (18); B
140 PRINT CHR $ (31 ); RO $ (19);
150 A $ = "MIENTRAS SE PUEDE UTILIZAR LA VENTANA PRINCIPAL": GOSUB 300: IMPRIMA B $
160 A $ = "PARA ACEPTAR COMANDOS": GOSUB 300: IMPRIMA B $
170 PARA I = 1 A 5000: SIGUIENTE I: POKE 53284 ,
0180 PARA I = 1 A 5:
190 PARA J = 1 A 300: SIGUIENTE J: POKE 53282,1
200 SIGUIENTE I: POKE 53283, -2 * (PEEK (53283) = 240): POKE 53284, -13 * (PEEK (53284) = 240)
210 GOTO 180
300 B $ = "": para i = 1TOLEN (A $): B = ASC (MID $ (A $, I, 1))
310 B = B + 32: IFB <96THENB = B + 96
320 B $ = B $ + CHR $ (B): NEXTI: RETURN

Bit 7. El bit 7 de este registro es el bit de orden superior (bit 8) del


registro de comparación de ráster en 53266 ($ D012). Aunque se encuentra
aquí, funciona como parte de ese registro (consulte la descripción a continuación
para obtener más información sobre el registro de comparación de ráster).

Los programadores de lenguaje de máquina deben tener en cuenta que su posición aquí en el Bit
7 permite probar este bit con el indicador Negativo. Desde escanear líneas
por encima del número 256 están todos fuera de la pantalla, esto proporciona una manera fácil de
retrasar el cambio de la pantalla gráfica hasta que el escaneo esté en el
intervalo de supresión vertical y la pantalla ya no se

dibuje : LOOP LDA $ D011


BPL LOOP Los

Sprites siempre deben moverse cuando el ráster está escaneando fuera de la pantalla,
porque si se mueven mientras se escanean, sus formas
fluctuarán ligeramente.

El equivalente BASIC del fragmento de programa anterior es la instrucción


WAIT 53265,128, pero BASIC no suele ser lo suficientemente rápido para ejecutar la
siguiente instrucción mientras aún se encuentra en el intervalo de supresión.

53266 $ D012 RASTER


Leer línea de escaneo ráster actual / Escribir línea para comparar para IRQ ráster

El registro de comparación de ráster tiene dos funciones diferentes, dependiendo de


si está leyendo o escribiendo en él. Cuando
se lee este registro , indica qué línea de pantalla está
escaneando actualmente el haz de electrones .

Hay 262 líneas horizontales que componen la


pantalla de visualización estándar estadounidense (NTSC) (312 líneas en la
pantalla estándar europea o PAL ). Cada una de estas líneas se escanea y actualiza 60 veces por
segundo. Solo 200 de estas líneas (números 50-249) forman parte de la
pantalla visible.

A veces es útil saber qué línea se está escaneando,


porque cambiar los gráficos de la pantalla en una línea en particular mientras
se escanea esa línea puede causar una ligera interrupción en la pantalla. Por
Al leer este registro, es posible que un programa en lenguaje de máquina
espere hasta que el escaneo salga de la parte inferior de la pantalla antes de cambiar
la visualización de gráficos.

Incluso es posible que un programa de lenguaje de máquina lea este


registro y cambie la visualización de la pantalla cuando se
alcanza una determinada línea de exploración . El programa siguiente utiliza esta técnica para cambiar el
color de fondo en la pantalla intermedia, con el fin de mostrar las 256 combinaciones
de colores de texto de primer plano y de fondo a la vez.

40 PARA I = 49152 A 49188: LEER A: POKE I, A: SIGUIENTE: POKE 53280,11


50 IMPRIMIR CHR $ (147): FOR I = 1024 TO I + 1000: POKE I, 160: POKE I + 54272,11 : SIGUIENTE I
60 PARA I = 0 A 15: PARA J = 0 A 15
70 P = 1196 + (48 * I) + J: POKE P, J + I: POKE P + 54272, J: SIGUIENTE J, I
80 PESTAÑA DE IMPRESIÓN (15) CHR $ (5) "TABLA DE COLORES": PARA I = 1 A 19: IMPRIMIR: SIGUIENTE
85 IMPRIMIR "ESTE TABLA MUESTRA TODAS LAS COMBINACIONES DE"
86 IMPRESIÓN "DE COLORES DE PRIMER PLANO Y DE FONDO."
87 IMPRESIÓN "AUMENTOS DE PRIMER PLANO DE IZQUIERDA A DERECHA "
88 IMPRESIÓN" AUMENTOS DE FONDO DE ARRIBA A ABAJO "
90 SYS 12 * 4096
100 DATOS 169,90,133,251,169,0,141,33,208,162,15,120,173,17,208,48
105 DATOS 251,173,18,208
110 DATOS 197,251,208,249,238,33,208,24,105,8 16,233,48,219 La

escritura en este registro designa el valor de comparación para la


interrupción de comparación de ráster. Cuando esa interrupción está habilitada,
se emitirá una solicitud de interrupción enmascarable cada vez que el escaneo del haz de electrones
llega a la línea de escaneo cuyo número se escribió aquí. Esta es una
técnica mucho más flexible para cambiar la visualización en la pantalla media que
leer este registro como lo hace el programa de muestra anterior. Esa
técnica requiere que el programa observe continuamente el
Registro de ráster , mientras que el método de interrupción llamará al programa cuando sea el
momento adecuado para actuar. Para obtener más información sobre interrupciones de ráster, consulte
la entrada del Registro de máscara de interrupción (53274, $ D01A).

Es muy importante recordar que este registro requiere nueve


www.unusedino.de/ec64/technical/project64/mapping_c64.html 68/126
25/9/2020 Mapping The C64
bits y que esta ubicación solo contiene ocho de esos bits (el noveno
es el Bit 7 de 53265 ($ D011)). Si olvida leer o escribir al
noveno bit, sus resultados podrían ser erróneos por un factor de 256.

Por ejemplo, algunos de los primeros programas escritos para demostrar la


interrupción de ráster dieron por sentado que el noveno bit de este registro se
establecería en 0 en el encendido. Cuando una versión posterior del Kernal cambió
este valor inicial a 1, sus rutinas de interrupción, que se
suponía que debían configurar la interrupción de la trama para que ocurriera en la línea de exploración número 150,
terminaron configurándola para la línea número 406. Dado que los
números de línea de exploración no suben tanto, nunca se emitió ninguna solicitud de interrupción
y el programa no funcionó.

Rango de ubicación: 53267-53268 ($ D013- $ D014)


Registros de

lápiz de luz Un lápiz de luz es un dispositivo de entrada que se puede conectar al joystick
Puerto de control n. ° 1. Tiene la forma de un bolígrafo y tiene un
dispositivo sensible a la luz en su punta que hace que el gatillo del puerto del joystick se
cierre en el momento en que el haz de electrones que actualiza la pantalla lo
golpea. El chip VIC-II realiza un seguimiento de dónde está el haz
cuando eso sucede y registra las
coordenadas de pantalla horizontales y verticales correspondientes en los registros en estas ubicaciones.

Un programa puede leer la posición en la que se coloca el lápiz óptico en


la pantalla. Los valores de estos registros se actualizan una vez en cada
fotograma de la pantalla (60 veces por segundo). Una vez que se cierra el interruptor y se
escribe un valor en estos registros, los registros se bloquean y
los cierres de interruptores posteriores durante el mismo cuadro de pantalla no se
grabarán.

Es posible que una pluma de luz determinada no sea del todo precisa (y es posible que el operador
no tenga la mano firme). Probablemente sea conveniente promediar las posiciones
devueltas a partir de una serie de muestreos, especialmente cuando se utiliza un
controlador de lenguaje de máquina .

53267 $ D013 LPENX


Light Pen Posición horizontal

Esta ubicación mantiene la posición horizontal del lápiz óptico. Dado


que solo hay ocho bits disponibles (que dan un rango de 256 valores)
para 320 posibles posiciones horizontales de la pantalla, el valor aquí es
preciso solo para cada segunda posición de punto. El número aquí será
rango de 0 a 160 y debe multiplicarse por 2 para obtener una
aproximación cercana de la posición horizontal real del punto del
lápiz óptico.

53268 $ D014 LPENY


Posición vertical del lápiz óptico

Esta ubicación mantiene la posición vertical del lápiz óptico. Dado


que solo hay 200 líneas de exploración visibles en la pantalla, el valor de este
registro corresponde exactamente a la línea de exploración de trama actual.

53269 $ D015 SPENA


Sprite Enable Register

Bit 0: Activar Sprite 0 (1 = Sprite activado , 0 =


Sprite desactivado) Bit 1: Activar Sprite 1 (1 = Sprite activado, 0 =
Sprite desactivado) Bit 2: Activar Sprite 2 (1 = el sprite está encendido, 0 = el sprite está apagado)
Bit 3: Activar Sprite 3 (1 = Sprite activado, 0 =
Sprite desactivado) Bit 4: Activar Sprite 4 (1 = Sprite activado, 0 =
Sprite desactivado) Bit 5: Activar Sprite 5 (1 = Sprite activado , 0 =
Sprite desactivado) Bit 6: Habilitar Sprite 6 (1 = Sprite activado, 0 = Sprite desactivado)
Bit 7: Activado Sprite 7 (1 = Sprite activado, 0 = Sprite desactivado)

Para cualquier sprite para ser mostrado, el bit correspondiente en este


registro debe establecerse en 1 (el valor predeterminado para esta ubicación es 0). Por
supuesto, simplemente configurar este bit no garantizará que
se muestre un objeto en la pantalla. El Sprite Data Pointer debe indicar un
área de datos que contenga algunos valores distintos de 0. El Sprite Color
Register también debe contener un valor diferente al del fondo
color. Además, los
registros de posición horizontal y vertical de Sprite deben configurarse para las posiciones que se encuentran dentro del
rango de pantalla visible para que un sprite aparezca en la pantalla.

53270 $ D016 SCROLX


Registro de control y desplazamiento fino horizontal

Bits 0-2: Visualización de desplazamiento fino horizontalmente por posiciones de puntos X (0-7)
Bit 3: Seleccione una visualización de texto de 38 o 40 columnas (1 = 40 columnas,
0 = 38 columnas)
Bit 4: Habilitar texto multicolor o modo de mapa de bits multicolor (1 = multicolor encendido,
0 = multicolor apagado)
Bit 5: Restablecimiento del chip de video (0 = operaciones normales, 1 = video completamente apagado)
Bits 6-7: Sin usar

Esto es uno de los dos importantes registros de control multifunción en


el chip VIC-II. En el encendido, se establece en un valor predeterminado de 8, lo
que significa que la línea de reinicio del chip VIC está configurada para una pantalla normal, el
modo multicolor está desactivado, se selecciona una pantalla de texto de 40 columnas y
no hay desplazamiento fino horizontal se utiliza offset.

Bits 0-2. Los primeros tres bits de este chip controlan el


desplazamiento vertical fino de la pantalla. Esta función le permite
mover suavemente toda la pantalla de texto hacia adelante y hacia atrás, lo que permite que el área de visualización
actúe como una ventana, desplazándose sobre una pantalla de texto o gráficos de caracteres más grande
.
www.unusedino.de/ec64/technical/project64/mapping_c64.html 69/126
25/9/2020 Mapping The C64

Dado que cada carácter de texto tiene ocho puntos de ancho, mover cada carácter
sobre la posición de un carácter completo (conocido como desplazamiento aproximado) es una
salto relativamente grande, y el movimiento parece desigual. Al colocar un número
del 1 al 7 en estos tres bits, puede mover toda la pantalla
de uno a siete espacios de puntos hacia la derecha.

Pasar por los valores del 1 al 7 le permite realizar sin problemas la


transición de que un personaje aparezca en una columna de la pantalla a
que aparezca en la siguiente. Para demostrar esto, escriba
el siguiente programa, LISTA y EJECCIONE.

10 PARA I = 1 A 50: PARA J = 0 A 7


20 POKE 53270, (PEEK (53270) AND248) O J: SIGUIENTE J, I
30 PARA I = 1 A 50: PARA J = 7 A 0 PASO-1
40 POKE 53270, (PEEK (53270) AND248) O J: SIGUIENTE J, I

Como puede ver, después de que la pantalla se ha movido más de siete puntos, comienza
en su posición original. Para continuar con el desplazamiento,
debe realizar un desplazamiento aproximado cada vez que el valor de los bits de desplazamiento
va de 7 a 0, o de 0 a 7. Esto se logra moviendo cada
byte de datos de visualización en cada línea sobre una posición , sobrescribiendo el
último carácter e introduciendo un nuevo byte de datos en el extremo opuesto
de la línea de pantalla para reemplazarlo.

Obviamente, solo un programa en lenguaje de máquina puede mover todos estos bytes
lo suficientemente rápido como para mantener el efecto de movimiento suave. El siguiente
programa BÁSICO, sin embargo, le dará una idea de cómo es la combinación
de desplazamiento fino y grueso.

10 POKE 53281,0: IMPRIMIR CHR $ (5); CHR $ (147): PARA I = 1 A 5: IMPRIMIR CHR $ (17): SIGUIENTE
20 FOR I = 1 TO 30
30 PRINT TAB (I-1) "{UP} {10 SPACES} {UP}"
40 WAIT53265,128: POKE53270, PEEK (53270) AND248: PRINTTAB (I) "AWAY WE GO"
50 FOR J = 1 TO 7
60 POKE 53270, (PEEK (53270) AND248) + J
70 FORK = 1TO30-I
80 NEXT K, J, I: RUN

Cambiar el valor de los tres bits de desplazamiento horizontal afectará a


toda la pantalla. Si desea desplazarse solo una parte de la
pantalla, tendrá que usar interrupciones de trama (consulte 53274 ($ D01A) a
continuación) para establecer una zona de desplazamiento, cambie el valor de estos
bits de desplazamiento solo cuando se muestre esa zona, y cámbielo de nuevo a 0
después.

Bit 3. El bit 3 de este registro le permite cubrir el primero y


Las últimas columnas de la pantalla se muestran con el borde. Dado que los espectadores
no pueden ver los caracteres allí, no podrán verlo
insertar un nuevo carácter al final de la línea cuando realice un
desplazamiento aproximado (consulte la explicación de los bits 0-2 más arriba).

Establecer este bit en 1 habilita la visualización normal de 40 columnas, mientras que


restablecerlo a 0 cambia la visualización a 38 columnas. Esta es una
ayuda puramente cosmética y no es necesario cambiar la pantalla a
un tamaño más pequeño para usar la función de desplazamiento.

Bit 4. Este bit selecciona gráficos multicolores. El efecto de establecer


este bit en 1 depende de si el modo de gráficos de mapa de bits
también está habilitado.

Si no está en el modo de mapa de bits y selecciona el


modo de caracteres de texto multicolor estableciendo este bit en 1, los caracteres con un color
nybble cuyo valor es inferior a 8 se muestran normalmente. Habrá
un color de fondo y un color de primer plano. Pero cada punto de un
carácter con un color nybble cuyo valor sea superior a 7 puede tener uno
de cuatro colores diferentes.

Los dos colores de los registros de control de fondo 1 y 2 (53282-3,


$ D022-3) están disponibles además de los colores suministrados por la
RAM de color . El precio de estos colores adicionales es una reducción en la
resolución horizontal . En lugar de que cada bit controle un punto, en el
modo multicolor un par de bits controlan el color de un punto más grande. Un patrón de
11 lo iluminará con el color de los tres bits inferiores de la
RAM de color . Los patrones 01 y 10 seleccionarán los colores de los
registros de color de fondo 1 y 2, respectivamente, para el punto de doble ancho.

Puede ver el efecto que tiene establecer este bit escribiendo la


siguiente línea de comando BÁSICA:

POKE 53270, PEEK (53280) OR16: PRINT CHR $ (149) "ESTE ES EL MODO MULTICOLOR"

Es obvio en este ejemplo que el conjunto normal de caracteres de texto


no se hizo para usarse en modo multicolor. Para
aprovechar este modo, deberá diseñar
personajes personalizados de cuatro colores . Para obtener más información, consulte la entrada alternativa para 53248
($ D000), la ROM del generador de caracteres.

Si los bits de habilitación de mapa de bits y multicolor se establecen en 1, el resultado


es un modo de mapa de bits multicolor. Como en el modo de texto multicolor,
se utilizan pares de bits de datos gráficos para establecer cada punto en una matriz de 4 por 8 en uno
de cuatro colores. Esto da como resultado una reducción de la
resolución horizontal a 160 puntos de doble ancho. Pero mientras que el
modo multicolor de texto permite que solo uno de los cuatro colores se establezca individualmente para
cada área de 4 por 8 puntos, el modo multicolor de mapa de bits permite seleccionar hasta tres
colores diferentes individualmente en cada área de 4 por 8 puntos.
La fuente del color del punto para cada combinación de pares de bits se muestra a
continuación:
www.unusedino.de/ec64/technical/project64/mapping_c64.html 70/126
25/9/2020 Mapping The C64

00 Registro de color de fondo 0 (53281, $ D021)


01 Cuatro bits superiores de la matriz de video
10 Los cuatro bits inferiores de Video Matrix
11 Color RAM nybble (el área comienza en 55296 ($ D800))

El hecho de que se usen pares de bits en este modo cambia un poco la estrategia para
trazar. Para encontrar el byte BY en el que
reside el par de bits deseado , debe multiplicar la posición horizontal X, que
tiene un valor de 0 a 159, por 2, y luego usar la misma fórmula que para el
modo de mapa de bits de alta resolución.

Dado que la posición horizontal (0-159) del punto se almacena en la


variable X, su posición vertical está en la variable Y, y la
dirección base del área del mapa de bits ia en la variable BASE, puede encontrar el
byte deseado con la fórmula:

POR = BASE + (Y Y 248) * 40 + (Y Y 7) + (2 * X Y 504)

La configuración del par de bits deseado dependerá del color que elija.
Primero, debe configurar una matriz de máscaras de bits.

CA (0) = 1: CA (1) = 4: CA (2) = 16: CA (3) = 64

Para encender el punto deseado, seleccione un color CO de 0 a 3


(que representa el color seleccionado por el correspondiente patrón de bits) y
ejecute la siguiente declaración:

BI = (NOT X AND 3): POKE BY, PEEK (BY) AND (NOT 3 * CA (BI)) OR (CO * CA (BI))

El siguiente programa demostrará esto técnica:

10 CA (0) = 1: CA (1) = 4: CA (2) = 16: CA (3) = 64: ARRAY REM PARA PARES DE BITS
20 BASE = 2 * 4096: POKE53272, PEEK (53272) OR8 : REM PUT MAPA DE BITS EN 8192
30 POKE53265, PEEK (53265) OR32: POKE53270, PEEK (53270) OR16: REM MULTICOLOR BIT MAP
40 A $ = "": PARA I = 1 A 37: A $ = A $ + "C": SIGUIENTE: IMPRIMIR CHR $ (19);
50 FOR I = 1 TO 27: PRINT A $ ;: NEXT: POKE 2023, PEEK (2022): REM SET COLOR MAP
60 A $ = "": FOR I = 1 TO 128: A $ = A $ + "@" : NEXT: FOR I = 32 TO 63 STEP 2
70 POKE648, I: PRINTCHR $ (19); A $; A $; A $; A $: NEXT: POKE648,4: REM CLR HI-RES SCREEN
80 PARA CO = 1TO3: PARA Y = 0TO199 PASO.5: REM DESDE LA PARTE SUPERIOR DE LA PANTALLA HASTA LA PARTE INFERIOR
90 X = INT (10 * CO + 15 * SIN (CO * 45 + Y / 10)): FORMA
DE ONDA SINusoidal REM 100 BY = BASE + 40 * (Y Y 248) + (Y Y 7) + (X * 2 Y 504): REM ENCONTRAR BYTE DE ALTA RESOLUCIÓN
110 BI = (NO X Y 3): PASAR POR, ESCUCHAR (POR) Y (NO 3) * CA (BI)) OR (CO * CA (BI))
120 SIGUIENTE Y, CO
130 GOTO 130: REM DEJARLO EN PANTALLA

Bit 5: El bit 5 controla la línea de reinicio del chip VIC-II. Establecer este bit
en 1 detendrá completamente el funcionamiento del chip de video. En mayores
64s, la pantalla se volverá negra. Siempre debe establecerse en 0 para asegurar
el funcionamiento normal del chip.

Bits 6 y 7. Estos bits no se utilizan.

53271 $ D017 YXPAND


Sprite Registro de expansión vertical

Bit 0: Expandir Sprite 0 verticalmente (1 = doble altura, 0 = altura normal)


Bit 1: Expandir Sprite 1 verticalmente (1 = doble altura, 0 = altura normal)
Bit 2: Expandir Sprite 2 verticalmente (1 = doble altura, 0 = altura normal)
Bit 3: Expandir Sprite 3 verticalmente (1 = doble altura, 0 = altura normal)
Bit 4: Expandir Sprite 4 verticalmente (1 = doble altura, 0 = altura normal)
Bit 5 : Expandir Sprite 5 verticalmente (1 = doble altura, 0 = altura normal)
Bit 6: Expandir Sprite 6 verticalmente (1 = doble altura, 0 = altura normal)
Bit 7: Expandir Sprite 7 verticalmente (1 = doble altura, 0 = altura normal)

Este registro puede usarse para duplicar la altura de cualquier sprite. Cuando
el bit de este registro que corresponde a un objeto en particular se
establece en 1, cada punto de la matriz de puntos del objeto de 24 por 21 se convertirá en dos
líneas de barrido de trama de altura en lugar de una.

53272 $ D018 VMCSB


Registro de control de memoria de chip VIC-II

Bit 0:
Bits no utilizados 1-3: Dirección de base de datos de puntos de caracteres de texto dentro del
espacio de direcciones VIC-II
Bits 4-7: Dirección base de la matriz de video dentro del espacio de direcciones VIC-II

Este registro afecta prácticamente a todas las operaciones gráficas. Se


determina la dirección jarrón de dos áreas de datos muy importante, el
Video Matrix y el área Character Dot-Data.

Bits 1-3. Estos bits se utilizan para establecer la ubicación del


área de datos de puntos de caracteres . Esta área es donde se almacenan los datos (para
obtener más información sobre los datos de forma de caracteres, consulte la entrada alternativa para la
ubicación 53248 ($ D000), la ROM del generador de caracteres).

Los bits 1-3 pueden representar cualquier número par del 0 al 14. Ese número
representa el desplazamiento par de 1K del área de datos de caracteres desde el
comienzo de la memoria VIC-II. Por ejemplo, si estos bits están todos configurados en
0, significa que la memoria de caracteres ocupa los primeros 2K de la
memoria VIC-II . Si son iguales a 2, el área de datos comienza 2 * 1K (2 * 1024) o 2048
bytes desde el comienzo de la memoria VIC.

El valor predeterminado de este nybble es 4. Esto establece la dirección del área


Character Dot-Data en 4096 ($ 1000), que es la dirección
de inicio donde el chip VIC-II se dirige a la ROM de caracteres. El
juego de caracteres normal que contiene mayúsculas y gráficos ocupa los primeros
www.unusedino.de/ec64/technical/project64/mapping_c64.html 71/126
25/9/2020 Mapping The C64
2K de esa ROM. El conjunto de caracteres alternativo que contiene
letras mayúsculas y minúsculas utiliza el segundo 2K. Por lo tanto, para cambiar
al conjunto de caracteres alternativo, debe cambiar el valor de este
nybble a 6, con un POKE 53272, PEEK (53272) OR2. Para volver a cambiarlo,
POKE 53272, PEEK (53272) AND253.

En el modo de mapa de bits, el nybble inferior controla la ubicación de los


datos de la pantalla de mapa de bits . Dado que esta área de datos solo puede comenzar con un desplazamiento de 0 o
8K desde el comienzo de la memoria VIC-II, solo el bit 3 del
registro de control de memoria es significativo en el modo de mapa de bits. Si el bit 3 tiene un 0,
el desplazamiento es 0, y si tiene un 1, el desplazamiento es 8192 (8K).

Bits 4-7. Este nybble determina la dirección de inicio del


área Video Matrix. Esta es el área de memoria de 1024 bytes que contiene los
códigos de pantalla para los caracteres de texto que se muestran en la pantalla.
Además, los últimos ocho bytes de esta área se utilizan como punteros
que designan qué bloque de 64 bytes de memoria VIC-II se utilizará como
datos de forma para cada objeto.

Estos cuatro bits pueden representar números del 0 al 15. Estos números
representan el desplazamiento (en incrementos de 1K) desde el comienzo de VIC-II
memoria a Video Matrix.

Por ejemplo, el patrón de bits predeterminado es 0001. Esto indica que la


matriz de video está desplazada 1K desde el comienzo de la memoria VIC-II, el
lugar de inicio normal para la memoria de pantalla. Sin embargo, recuerde que el
valor de bit de este número será 16 veces mayor que lo que indica el patrón de bit,
porque estamos tratando con los Bits 4-7. Por lo tanto, 0001 en el
nibble superior tiene un valor de 16.

Usando este registro, podemos mover el inicio de la memoria de pantalla a cualquier


límite de 1K dentro del área de memoria de 16K VIC-II.
Sin embargo, cambiar este registro no es suficiente si desea utilizar el
editor de líneas BASIC . El editor busca en la ubicación 648 ($ 288) para determinar dónde
imprimir los caracteres de la pantalla.

Si simplemente cambia la ubicación de Video Matrix sin cambiar


el valor en 648, BASIC continuará imprimiendo caracteres en el
área de memoria a partir de 1024, aunque esa área ya no se
muestre. El resultado es que no podrá ver nada de lo
que escriba en el teclado. Para solucionar este problema, debe POKE 648 con
el número de página de la dirección inicial de la memoria de la pantalla (
número de página = ubicación / 256). Recuerde, la dirección de inicio real de la
memoria de pantalla depende no solo del desplazamiento desde el comienzo de la
memoria VIC-II en el registro, sino también de qué banco de 16K se usa para la
memoria VIC-II.

Por ejemplo, si el área de la pantalla comienza 1024 bytes desde el principio


de la memoria VIC-II, y el chip de video usa el Banco 2 (32768-49151),
la dirección de inicio real de la memoria de pantalla es 32768 + 1024 = 33792
($ 8400). Para ver ejemplos de cómo cambiar el área de la memoria de video y
cómo reubicar la pantalla, vea la introducción para 56576 ($ DD00).

53273 $ D019 VICIRQ


VIC Registro de bandera de interrupción

Bit 0: Bandera: ¿Es la comparación de ráster una posible fuente de una IRQ?
(1 = sí)
Bit 1: Bandera: ¿Es una colisión entre un objeto y la
pantalla de gráficos normal una posible fuente de una IRQ? (1 = sí)
Bit 2: Bandera: ¿Es una colisión entre dos sprites una posible fuente de
una IRQ? (1 = si)
Bit 3: Bandera: ¿Es el disparador del lápiz óptico una posible fuente de una IRQ?
(1 = sí)
Bits 4-6: No se usa
Bit 7: Bandera: ¿Existe alguna fuente de IRQ de chip VIC-II que pueda causar
una IRQ? (1 = sí)

El chip VIC-II es capaz de generar una solicitud enmascarable (IRQ) cuando se


cumplen ciertas condiciones relacionadas con la visualización de video.
Brevemente, las condiciones que pueden causar una IRQ de chip VIC-II son:

1. El número de línea de la línea de pantalla actual que está siendo escaneada por el
ráster es el mismo que el valor del número de línea escrito en el
Registro de Ráster (53266, $ D012).

2. Un objeto se coloca en la misma ubicación donde


se muestran los datos gráficos normales .

3. Se colocan dos objetos de modo que se toquen.

4. El sensor de luz del lápiz óptico ha sido golpeado por el


haz de trama , lo que hace que se
cierre el interruptor del botón de disparo del puerto de control n. ° 1 del joystick (presionar el botón de disparo del joystick puede tener e

Cuando se cumple una de estas condiciones, el bit correspondiente en este


registro de estado se establece en 1 y se bloquea. Eso significa que siempre que
el bit de habilitación correspondiente en el registro de máscara de IRQ de VIC se establezca en 1,
se generará la IRQ solicitada y
se ignorará cualquier cumplimiento posterior de la misma condición hasta que se borre el pestillo.

Esto le permite conservar múltiples solicitudes de interrupción si más de


una de las condiciones de interrupción se cumple a la vez. Para evitar que una
fuente de IRQ genere otra solicitud después de haber sido atendida,
y para permitir que se detecten las condiciones de interrupción posteriores, la
rutina del servicio de interrupciones debe escribir un 1 en el bit correspondiente.
Esto despejará el pestillo de ese bit. El valor predeterminado escrito en
este registro es 15, que borra todas las interrupciones.
www.unusedino.de/ec64/technical/project64/mapping_c64.html 72/126
25/9/2020 Mapping The C64

Solo hay 1 vector de IRQ que apunta a la dirección de la rutina


que se ejecutará cuando ocurra una interrupción de IRQ. Por
lo tanto, la misma rutina se ejecutará independientemente del origen de la interrupción.
Este registro de estado proporciona un método para que esa rutina verifique qué
la fuente de la IRQ fue, para que la rutina pueda tomar la
acción apropiada . Primero, la rutina puede verificar el Bit 7. Siempre que cualquiera de los
otros bits en el registro de estado se establezca en 1, el Bit 7 también se establecerá.
Por lo tanto, si ese bit tiene un 1, sabrá que el chip VIC-II
solicitó un IRQ (los dos chips CIA que son las otras fuentes de
interrupciones IRQ se pueden verificar de manera similar). Una vez que se ha
determinado que el chip VIC es responsable de la IRQ,
se pueden probar los bits individuales para ver cuál de las condiciones de la IRQ se
ha cumplido.

Para obtener más información y un programa de IRQ VIC de muestra, consulte la siguiente
entrada.

53274 $ D01A IRQMASK


Registro de máscara IRQ

Bit 0: Habilitar IRQ de comparación de ráster (1 = interrupción habilitada)


Bit 1: Habilitar IRQ para que ocurra cuando el sprite colisiona con la visualización de
datos gráficos
normales (1 = interrupción habilitada)
Bit 2: Habilitar IRQ para que ocurra cuando dos sprites chocan (1 = interrumpir
habilitado)
Bit 3: Habilita el lápiz óptico para activar una IRQ (1 = interrupción habilitada)
Bits 4-7: No se usa

Este registro se usa para permitir que ocurra una solicitud de IRQ cuando
se cumple una de las condiciones de interrupción del chip VIC-II. Para comprender
lo que eso significa y cómo estas interrupciones pueden extender el rango de
opciones disponibles para un programador, primero debe comprender qué es una
interrupción.

Una interrupción es una señal dada al microprocesador (el cerebro de


la computadora) que le dice que deje de ejecutar su
programa en lenguaje de máquina (por ejemplo, BASIC) y que trabaje en otro programa por un
tiempo corto, quizás solo una fracción de un tiempo. segundo. Después de terminar el
programa de interrupción, la computadora vuelve a ejecutar el
programa principal , como si nunca hubiera habido un desvío.

Bit 0. Este bit habilita la IRQ de comparación de ráster. Las condiciones para
esta IRQ se cumplen cuando el escaneo de trama alcanza la línea de video indicada
por el valor escrito en el Registro de trama en 53266 ($ D012) y el Bit 7
de 53265 ($ D011). Una vez más, conviene dar una explicación de la terminología
.

En la pantalla de TV normal, un haz de electrones (raster) escanea la


pantalla, comenzando en la esquina superior izquierda y moviéndose en línea recta
hacia la derecha, iluminando las partes apropiadas de la línea de la pantalla en el
camino. Cuando se trata del borde derecho, el rayo se mueve por una línea y
comienza de nuevo desde la izquierda. Hay 262 líneas de este tipo que son escaneadas
por la pantalla 64, 200 de las cuales forman el área de pantalla visible. Este
escaneo actualiza la visualización de la pantalla completa 60 veces por segundo.

El chip VIC-II realiza un seguimiento de qué línea se está escaneando y almacena


el número de escaneo en el Registro de tramas en 53266 y 53265 ($ D012 y
$ D011). El registro de ráster tiene dos funciones. Cuando se lee, dice
qué línea se está escaneando actualmente. Pero cuando se escribe,
designa una línea de exploración particular como el lugar donde
se producirá una interrupción de la trama .

En el momento exacto en que el número de línea del haz de trama es igual al número
escrito en el registro, el bit 0 del registro de estado se establecerá en
1, lo que muestra que se
han cumplido las condiciones para una interrupción de comparación de tramas. Si la interrupción de ráster está habilitada, entonces,
simultáneamente, se ejecutará el programa de interrupción. Esto permite
al usuario restablecer cualquiera de los registros VIC-II en cualquier punto de la
pantalla y así cambiar los juegos de caracteres, el color de fondo o el
modo de gráficos solo para una parte de la pantalla.

La rutina de interrupción primero verificará si la condición deseada es la


fuente de la interrupción (vea la entrada anterior) y luego realizará los cambios en
la pantalla. Una vez que haya escrito esta rutina de interrupción,
debe seguir los siguientes pasos para instalarla.

1. Configure la bandera de desactivación de interrupciones en el registro de estado con una


instrucción SEI . Esto desactivará todas las interrupciones y evitará que el sistema
falle mientras cambia los vectores de interrupción.

2. Habilite la interrupción de la trama. Esto se hace estableciendo el Bit 0 del


registro de habilitación de interrupciones del chip VIC-II en la ubicación 53274 ($ D01A) en 1.

3. Indique la línea de exploración en la que desea que ocurra la interrupción mediante


escribiendo en los registros raster. No olvide que este es un
valor de nueve bits , y debe establecer tanto el byte bajo (en la ubicación 53266 ($ D012))
como el bit alto (en el registro en 53265 ($ D011)) para asegurar
que la interrupción comenzará en la línea de escaneo que desea, y no
256 líneas antes o después.

4. Informe a la computadora dónde


comienza la rutina de lenguaje de máquina que desea que ejecute la interrupción. Esto se hace colocando la
dirección en el vector de interrupción en las ubicaciones 788-789 ($ 314- $ 315).
Esta dirección se divide en dos partes, un byte bajo y un byte alto, con
el byte bajo almacenado en 788.

www.unusedino.de/ec64/technical/project64/mapping_c64.html 73/126
25/9/2020 Mapping The C64
Para calcular los dos valores para una dirección dada AD, puede usar el
fórmula HIBYTE = INT (AD / 156) y LOWBYTE = AD- (HIBYTE * 256). El valor
LOWBYTE iría a la ubicación 788 y el valor HIBYTE iría a la
ubicación 789.

5. Vuelva a habilitar las interrupciones con una instrucción CLI, que borra el
indicador de inhabilitación de interrupciones en el registro de estado.

Cuando la computadora se enciende por primera vez, el vector de interrupción se establece para
apuntar a la rutina de interrupción del temporizador de hardware normal, la que hace
avanzar el jiffy clock y lee el teclado. Dado que esta
rutina de interrupción usa el mismo vector que la rutina de interrupción de ráster, es
mejor apagar la interrupción del temporizador de hardware poniendo un valor de
127 en la ubicación 56333 ($ DC0D).

Si desea que el teclado y el reloj jiffy funcionen normalmente mientras


su interrupción está habilitada, debe conservar el contenido de las ubicaciones
788 y 789 antes de cambiarlas para que apunten a su nueva rutina. Luego
, debe hacer que su rutina de interrupción salte a la rutina de interrupción anterior
exactamente una vez por actualización de pantalla (cada 1/60 de segundo).

Otra cosa que debe tener en cuenta es que


se requieren al menos dos interrupciones ráster si desea cambiar solo una parte de la
pantalla. La rutina de interrupción no solo debe cambiar la visualización, sino
que también debe configurar otra salida de ráster que la cambie nuevamente.

El programa de muestra a continuación utiliza una interrupción de exploración de trama para dividir
mostrar en tres secciones. Las primeras 80 líneas de escaneo están en
modo de mapa de bits de alta resolución, las 40 siguientes son texto normal y las
últimas 80 están en modo de mapa de bits multicolor. La pantalla se dividirá de esta manera
tan pronto como ocurra un SYS a la rutina que activa la interrupción.
La pantalla permanecerá dividida incluso después de que finalice el programa. Solo si
presiona las teclas STOP y RESTORE juntas, la pantalla volverá a la
normalidad.

La interrupción utiliza una tabla de valores que se colocan en cuatro


ubicaciones clave durante cada una de las tres interrupciones, así como valores para
determinar en qué líneas de exploración ocurrirá la interrupción. Las ubicaciones
afectadas son Registro de control 1 (53265, $ D011), Registro de control 2
(53270, $ D016), el registro de control de memoria (53272, $ D018) y el
color de fondo 0 (53281, $ D021). Los datos de la rutina de interrupción
se encuentran en las líneas 49152-49276. Cada uno de estos números de línea
corresponde a las ubicaciones donde
se introduce en la memoria el primer byte de datos de la declaración.

Si observa las líneas 49264-49276 del programa BASIC, verá


declaraciones REMark que explican qué registros VIC-II se ven afectados por
las declaraciones DATA en cada línea. El número en estos
estados de DATOS aparece en el orden inverso al que se colocan en el
registro VIC. Por ejemplo, la línea 49273 contiene los datos que irán
al Registro de control 2. El último número, 8, es el que será
colocado en el Registro de control 2 mientras se
muestra la parte superior de la pantalla . El primer número, 24, se coloca en el Registro de control 2
durante la parte inferior de la pantalla, y cambia esa parte
de la pantalla al modo multicolor.

La única parte complicada para determinar qué byte de datos afecta qué
interrupción viene en la línea 49264, que contiene los datos que determinan
la línea de exploración en la que se producirá cada interrupción. Cada
entrada de la instrucción DATA refleja la línea de exploración en la que se producirá la siguiente interrupción.
El primer elemento en la línea 49264 es 49. Aunque esta es la entrada para
la tercera interrupción, la siguiente que se genera es la primera interrupción,
que ocurre en la parte superior de la pantalla. Asimismo, el último elemento
de datos de 129 se utiliza durante la primera interrupción para iniciar la siguiente interrupción
en la línea de exploración 129.

Intente experimentar con estos valores para ver qué resultados obtiene
. Por ejemplo, si cambia el número 170 a 210,
aumentará el área de texto en cinco líneas (40 líneas de escaneo).

Al cambiar los valores en las tablas de datos, puede alterar el efecto de


cada interrupción. Cambie el 20 en la línea 49276 a 22, y obtendrá un
texto en minúsculas en el medio de la pantalla. Cambie los primeros 8 en la
línea 49273 a 24 y obtendrá un texto multicolor en la ventana central.
Cada uno de estos elementos de la tabla puede usarse exactamente como usaría el
registro correspondiente, para cambiar el color de fondo, obtener
texto o gráficos de mapa de bits, modos regular o multicolor, pantalla en
blanco o modo de color de fondo extendido.

Incluso es posible cambiar los valores de la tabla durante un programa,


introduciendo el nuevo valor en la ubicación de la memoria donde
se almacenan esos valores de la tabla . De esa manera, puede, por ejemplo, cambiar el
color de fondo de cualquiera de las partes de la pantalla mientras se
ejecuta el programa .

5 PARA I = 0 A 7: BI (I) = 2 ^ I: SIGUIENTE


10 PARA I = 49152 A 49278: LEER A: POKE I, A: SIGUIENTE: SYS12 * 4096
20 IMPRIMIR CHR $ (147): FOR I = 0 A 8: IMPRIMIR: SIGUIENTE
30 IMPRIMIR "EL ÁREA SUPERIOR ES EL MODO DE MAPA DE BITS DE ALTA RESOLUCIÓN"
40 IMPRIMIR: IMPRIMIR "EL ÁREA MEDIA ES TEXTO ORDINARIO"
50 IMPRESIÓN: IMPRIMA "EL ÁREA INFERIOR ES UN MAPA DE BITS
MULTICOLOR " 60 FORG = 1384 A 1423: POKE G, 6: SIGUIENTE
70 FORG = 1024 A 1383: POKEG, 114: POKE G + 640,234: SIGUIENTES
80 A $ = " ": PARA I = 1 A 128: A $ = A $ +" @ ": SIGUIENTE: PARA I = 32 A 63 PASO 2
90 POKE 648, I: IMPRIMA CHR $ (19) CHR $ (153); A $; A $; A $; A $: SIGUIENTE: POKE 648,4
100 BASE = 2 * 4096: BK = 49267110
H = 40: C = 0: FORX = 0TO319: GOSUB150: SIGUIENTE
120 H = 160: C = 0: FORX = 0TO319STEP2: GOSUB150: NEXT: C =
www.unusedino.de/ec64/technical/project64/mapping_c64.html 74/126
25/9/2020 Mapping The C64
40125 FORX = 1TO319STEP2: GOSUB150: NEXT
130 C = 80: FOR X = 0 TO 319 STEP2: W = 0: GOSUB150: W = 1: GOSUB150: NEXT
140 GOTO 140150
Y = INT (H + 20 * SIN (X / 10 + C)): POR = BASE + 40 * (Y Y 248) + (Y Y 7) + (X Y 504)
160 PASAR POR, ESCUCHAR (POR) O ( BI (ABS (7- (XAND7) -W))): REGRESAR
49152 DATOS 120, 169, 127, 141, 13, 220
49158 DATOS 169, 1, 141, 26, 208, 169
49164 DATOS 3, 133, 251, 173, 112, 192
49170 DATOS 141, 18, 208, 169, 24, 141
49176 DATOS 17, 208, 173, 20, 3 , 141
49182 DATOS 110, 192, 173, 21, 3, 141
49188 DATOS 111, 192, 169, 50, 141, 20
49194 DATOS 3, 169, 192, 141, 21, 3
49200 DATOS 88, 96, 173, 25 , 208, 141
49206 DATOS 25, 208, 41, 1, 240, 43
49212 DATOS 190, 251, 16, 4, 169, 2
49218 DATOS 133, 251, 166, 251, 189, 115
49224 DATOS 192, 141, 33 , 208, 189, 118
49230 DATOS 192, 141, 17, 208, 189, 121
49236 DATOS 192, 141, 22, 208, 189, 124
49242 DATOS 192, 141, 24, 208, 189, 112
49248 DATOS 192, 141 , 18, 208, 138, 240
49254 DATOS 6, 104, 168, 104, 170, 104
49260 DATOS 64, 76, 49, 234
49264 DATOS 49, 170, 129: LÍNEAS
DE ESCANEO REM 49267 DATOS 0, 6, 0: COLOR
DE FONDO REM 49270 DATOS 59, 27,59: CONTROL REMOTO REG. 1
49273 DATOS 24, 8, 8: CONTROL REMOTO REG. 2
49276 DATA 24, 20, 24: REM MEMORY CONTROLRUN

Además de permitir la creación de pantallas de modos gráficos mixtos, la


interrupción de comparación de ráster también es útil para crear zonas de desplazamiento, de
modo que algunas partes de la pantalla se pueden desplazar con precisión mientras que el resto
permanece estacionario.

El bit 1 habilita la interrupción del lápiz óptico. Esta interrupción puede ocurrir cuando
la luz del rayo raster golpea el dispositivo sensible a la luz en la
punta del lápiz, haciendo que cierre el interruptor del botón de disparo en el joystick.
Puerto del controlador n. ° 1.

La interrupción del lápiz óptico proporciona un método de señalizar a un programa


que el lápiz se está sosteniendo en la pantalla y que se puede
leer su posición . Algunos bolígrafos de luz proporcionan un interruptor de botón que conecta a tierra una
de las otras líneas en el puerto del joystick. El
usuario puede presionar este interruptor como una señal adicional de que el lápiz está
colocado correctamente . Su ubicación se puede leer en los
registros de posición del lápiz óptico (53267-8, $ D013-4).

El bit 2 habilita la interrupción de colisión de sprite-foreground. Esta


interrupción puede ocurrir si uno de los puntos del carácter srpte toca
uno de los puntos de la visualización en primer plano del carácter de texto
o gráficos de mapa de bits.

El bit 3 habilita la interrupción de la colisión de sprite-sprite, que puede ocurrir


si uno de los puntos del personaje de sprite toca uno de los puntos de
otro personaje de sprite.

Estas dos interrupciones son útiles para juegos, donde tales colisiones a menudo
requieren que se tome alguna acción de inmediato. Una vez que la interrupción
indica que ha ocurrido una colisión, la rutina de interrupción puede verificar
el
Sprite- Foreground Collision Register en 53279 ($ D01F), o el Sprite-Sprite Collision Register en 53278 ($ D01E), para ver qué sprite
o sprites están involucrados. en la colisión. Consulte la entrada para esas
ubicaciones para obtener más detalles sobre colisiones.

53275 $ D01B SPBGPR


Sprite al registro de prioridad de visualización en primer plano

Bit 0: Selecciona la prioridad de visualización del Sprite 0 al primer plano (0 = el sprite


aparece delante del primer plano)
Bit 1: Selecciona la prioridad de visualización del Sprite 1 al primer plano (0 = el sprite
aparece delante del primer plano)
Bit 2: Selecciona la prioridad de visualización del Sprite 2 al primer plano (0 = el sprite
aparece delante del primer plano)
Bit 3: selecciona la prioridad de visualización del Sprite 3 al primer plano (0 = el sprite
aparece delante del primer plano)
Bit 4: Selecciona la prioridad de visualización del Sprite 4 al primer plano (0 =
aparece el sprite delante del primer plano)
Bit 5: Seleccione la prioridad de visualización del Sprite 5 al primer plano (0 = el objeto
aparece delante del primer plano)
Bit 6: Seleccione la prioridad de visualización del Sprite 6 al primer plano (0 = el sprite
aparece delante del primer plano)
Bit 7: Seleccione la prioridad de visualización del Sprite 7 al primer plano (0 = el sprite
aparece delante del primer plano)

Si un sprite está posicionado para aparecer en un lugar en la pantalla que


ya está ocupado por texto o gráficos de mapa de bits, surge un conflicto. El
contenido de este registro determina cuál se mostrará en
tal situación. Si el bit que corresponde a un objeto en particular
se establece en 0, el objeto se mostrará delante de los
datos gráficos en primer plano . Si ese bit se establece en 1, los datos de primer plano se
mostrarán frente al sprite. El valor predeterminado que este
el registro está configurado en el encendido es 0, por lo que todos los sprites comienzan con
prioridad sobre los gráficos de primer plano.

Tenga en cuenta que, a efectos de prioridad, se considera que el par de bits 01 de


modos de gráficos multicolores muestra un color de fondo y,
por lo tanto, se mostrará detrás de los gráficos de sprites incluso si los
www.unusedino.de/ec64/technical/project64/mapping_c64.html 75/126
25/9/2020 Mapping The C64
datos de los gráficos de primer plano tienen prioridad. Además, entre los propios sprites
hay una prioridad fija. Cada sprite tiene prioridad sobre todos
los sprites de mayor número, de modo que el Sprite 0 se muestra frente a todos
los demás.

El uso de la prioridad puede ayudar a crear efectos tridimensionales, al


permitir que algunos objetos en la pantalla pasen por delante o por detrás de
otros objetos.

53276 $ D01C SPMC


Sprite Multicolor Registers

Bit 0: Seleccione el modo multicolor para Sprite 0 (1 = multicolor, 0 = alta resolución)


Bit 1: Seleccione el modo multicolor para Sprite 1 (1 = multicolor, 0 = alta resolución)
Bit 2: Seleccione el modo multicolor para Sprite 2 (1 = multicolor, 0 = alta resolución)
Bit 3: Seleccione el modo multicolor para Sprite 3 (1 = multicolor, 0 = alta resolución)
Bit 4: Seleccione el modo multicolor para Sprite 4 (1 = multicolor , 0 = alta resolución)
Bit 5: Seleccione el modo multicolor para Sprite 5 (1 = multicolor, 0 = alta resolución)
Bit 6: Seleccione el modo multicolor para Sprite 6 (1 = multicolor, 0 = alta resolución)
Bit 7: Seleccione el modo multicolor para Sprite 7 (1 = multicolor, 0 = alta resolución) El

modo Sprite multicolor es muy similar al texto y mapa de bits multicolor


modos (ver Bit 4 de 53270, $ D016). Normalmente, el color de cada punto del
sprite está controlado por un solo bit de datos de forma del sprite. Cuando
este modo está habilitado para un sprite, al establecer el bit correspondiente de
este registro en 1, los bits de datos de forma del sprite se agrupan
en pares, con cada par de bits controlando un punto de doble ancho de la
pantalla del sprite. Al sacrificar parte de la resolución horizontal (el
sprite, aunque tiene el mismo tamaño, ahora solo tiene 12 puntos de ancho), obtiene
el uso de dos colores adicionales. Las cuatro combinaciones posibles de
estos pares de bits muestran colores de puntos de las siguientes fuentes:

00 Registro de color de fondo 0 (transparente)


01 Registro multicolor de Sprite 0 (53285, $ D025)
10 Registros de color de Sprite (53287-94, $ D027-E)
11 Registro de Sprite Multicolor 1 (53286, $ D026)

Al igual que los caracteres de texto multicolores, los sprites multicolores comparten dos
registros de color. Si bien cada objeto puede mostrar tres
colores de primer plano , solo uno de estos colores es exclusivo de ese objeto. El número
de colores únicos se puede incrementar combinando más de un sprite
en un solo personaje.

53277 $ D01D XXPAND


Sprite Registro de expansión horizontal

Bit 0: Expandir Sprite 0 horizontalmente (1 = Sprite de doble ancho, 0 =


ancho normal )
Bit 1: Expandir Sprite 1 horizontalmente (1 = Sprite de doble ancho, 0 =
ancho normal )
Bit 2: Expandir Sprite 2 horizontalmente (1 = Sprite de doble ancho, 0 =
ancho normal )
Bit 3: Expandir Sprite 3 horizontalmente (1 = Sprite de doble ancho, 0 =
ancho normal )
Bit 4: Expandir Sprite 4 horizontalmente (1 = sprite de doble ancho, 0 =
ancho normal )
Bit 5: Expandir Sprite 5 horizontalmente (1 = sprite de doble ancho, 0 =
ancho normal )
Bit 6: Expandir Sprite 6 horizontalmente (1 = sprite de doble ancho, 0 =
ancho normal )
Bit 7: Expandir el Sprite 7 horizontalmente (1 = sprite de doble ancho, 0 =
ancho normal )

Este registro se puede usar para duplicar el ancho de cualquier sprite. Establecer
cualquier bit de este registro en 1 hará que cada punto del correspondiente
la forma del sprite se mostrará el doble de ancho de lo normal, de modo que sin
cambiar su resolución horizontal, el sprite ocupe el doble de
espacio. La función de expansión horizontal se puede usar sola o en
combinación con el registro de expansión vertical en 53271 ($ D017).

Rango de ubicación: 53278-53279 ($ D01E- $ D01F) Se


registra la detección de colisión de sprites

mientras que el bit 2 del registro IRQ VIC en 53273 ($ D019) se establece en 1
siempre que dos sprites se superponen, y el bit 1 se establece en 1, cuando La
forma del sprite está tocando el texto en primer plano o la pantalla de gráficos de bits, estos
registros especifican qué sprites estuvieron involucrados en la colisión. Cada
bit que se establece en 1 indica que el sprite correspondiente fue
involucrado en la colisión. La lectura de estos registros los borra para
que puedan detectar la próxima colisión. Por lo tanto, si planea
realizar múltiples pruebas con los valores almacenados aquí, puede ser necesario
copiarlo a una variable RAM para referencia adicional.

Tenga en cuenta que, si bien estos registros le dicen qué sprites estuvieron involucrados en
una colisión, no necesariamente le dicen qué objetos han
chocado entre sí. Es muy posible tener tres sprites
alineados en una fila, donde Sprite A está a la izquierda, Sprite B está en el
medio, tocando Sprite A y Sprite C está a la derecha, tocando
Sprite B pero sin tocar Sprite A. La colisión Sprite-Sprite
El registro mostraría que los tres están involucrados. La única forma de estar
absolutamente seguro de cuál colisionó con cuál es verificar la posición
de cada sprite y calcular para cada línea de visualización de sprite si un sprite
de ese tamaño tocaría a cualquiera de los otros. Como puede imaginar,
esta no es una tarea fácil.

Hay algunas reglas simples sobre qué causa o no una


colisión. Aunque el carácter de sprite consta de 504 puntos en una
matriz de 24 por 21, ¿qué representa bits de datos que son iguales a 0 (o
www.unusedino.de/ec64/technical/project64/mapping_c64.html 76/126
25/9/2020 Mapping The C64
pares de bits multicolores iguales a 00) y, por lo tanto, siempre se muestran en
el color de fondo, no cuente cuando llega a la colisión.

Una colisión puede ocurrir solo si un punto que representa una forma de sprite
El bit de datos de 1 toca otro punto de datos gráficos distintos de cero. Considere
el caso de dos sprites invisibles. El primer sprite está habilitado, su
color está configurado para contrastar el fondo y está posicionado en la
pantalla, pero sus bytes de datos de forma son todos 0. Este sprite nunca puede estar
involucrado en una colisión, porque no muestra datos distintos de cero. El
segundo sprite está habilitado, posicionado en la pantalla, y su
puntero de forma se establece para una lectura de datos que está llena de bytes con un valor
de 255. Incluso si el color de ese sprite se establece en el mismo valor que el
color de fondo, el sprite invisible, aún puede estar
involucrado en colisiones. La única excepción a esta regla es la 01
par de bits de datos gráficos multicolores. Este par de bits se considera
parte del fondo y el punto que muestra nunca puede estar involucrado
en una colisión.

La otra regla para recordar acerca de las colisiones es que pueden ocurrir en
áreas que están cubiertas por el borde de la pantalla. La colisión entre los
sprites puede ocurrir cuando los sprites están fuera de la pantalla, y las colisiones
entre los sprites y los datos de visualización en primer plano pueden ocurrir cuando esos datos
están en un área que está cubierta por el borde debido a la reducción de
la visualización a 38 columnas o 24 filas.

53278 $ D01E SPSPCL


Sprite to Sprite Collision Register

Bit 0: ¿Sprite 0 chocó con otro sprite? (1 = si)


Bit 1: ¿Sprite 1 chocó con otro sprite? (1 = sí)
Bit 2: ¿Sprite 2 chocó con otro sprite? (1 = sí)
Bit 3: ¿Sprite 3 chocó con otro sprite? (1 = sí)
Bit 4: ¿Sprite 4 chocó con otro sprite? (1 = sí)
Bit 5: ¿Sprite 5 chocó con otro sprite? (1 = sí)
Bit 6: ¿Sprite 6 chocó con otro sprite? (1 = sí)
Bit 7: ¿Sprite 7 chocó con otro sprite? (1 = sí)

53279 $ D01F SPBGCL


Bit 0 del
registro de colisión de Sprite a primer plano
: ¿El Sprite 0 chocó con la pantalla de primer plano? (1 = sí)
Bit 1: ¿Sprite 1 chocó con la pantalla de primer plano? (1 = sí)
Bit 2: ¿Sprite 2 chocó con la pantalla de primer plano? (1 = si)
Bit 3: ¿Sprite 3 chocó con la pantalla de primer plano? (1 = sí)
Bit 4: ¿Sprite 4 chocó con la pantalla de primer plano? (1 = sí)
Bit 5: ¿Sprite 5 chocó con la pantalla de primer plano? (1 = sí)
Bit 6: ¿Sprite 6 chocó con la pantalla de primer plano? (1 = sí)
Bit 7: ¿Sprite 7 chocó con la pantalla de primer plano? (1 = sí)

Rango de ubicación: 53280-53294 ($ D020- $ D02E)


Registro de color VIC-II

Aunque estos registros de color se utilizan para varios propósitos, todos


tienen algo en común. Al igual que el Color RAM Nybbles, solo los
cuatro bits inferiores están conectados. Por lo tanto, al leer estos
registros, debe enmascarar los cuatro bits superiores (es decir,
BORDERCOLOR = PEEK (53280) AND15) para obtener una lectura verdadera.

53280 $ D020 EXTCOL


Registro de

color de borde El valor de color aquí determina el color del borde o marco
alrededor del área de visualización central. Toda la pantalla se establece en este
color cuando la función de supresión del Bit 4 de 53265 ($ D011) está habilitada.
El valor de color predeterminado es 14 (azul claro).

53281 $ D021 BGCOL0


Color de fondo 0

Este registro establece el color de fondo para todos los modos de texto,
gráficos de sprites y gráficos de mapa de bits multicolores. El valor de color predeterminado es
6 (azul).

53282 $ D022 BGCOL1


Color de fondo 1

Este registro establece el color para el par de bits 01 de


gráficos de caracteres multicolores y el color de fondo para los caracteres que tienen
códigos de pantalla 64-127 en el modo de texto de color de fondo extendido. El
valor de color predeterminado es 1 (blanco).

53283 $ D023 BGCOL2


Color de fondo 2

Este registro establece el color para el par de 10 bits de


gráficos de caracteres multicolores y el color de fondo para los caracteres que tienen
códigos de pantalla 128-191 en el modo de texto de color de fondo extendido. El
valor de color predeterminado es 2 (rojo).

53285 $ D024 BGCOL3


Color de fondo 3

Este registro establece el color de fondo para los caracteres que tienen pantalla
códigos entre 192 y 255 en el modo de texto de color de fondo extendido. El
valor de color predeterminado es 3 (cian).

53285 $ D025 SPMC0


Registro Sprite Multicolor 0
www.unusedino.de/ec64/technical/project64/mapping_c64.html 77/126
25/9/2020 Mapping The C64

Este registro establece el color que se muestra en el par de bits 01 en


gráficos de Sprite multicolor . El valor de color predeterminado es 4 (violeta).

53286 $ D026 SPMC1


Registro Sprite Multicolor 1

Este registro establece el color que se muestra en el par de 11 bits en


gráficos de Sprite multicolor . El valor de color predeterminado es 0 (negro).

Rango de ubicación: 53287-53294 ($ D027- $ D02E)


Registros de color de Sprite

Estos registros se utilizan para establecer el color que se mostrará por bits de
datos de sprites de alta resolución que tienen un valor de 1, y por pares de bits de
datos de sprites multicolores que tienen un valor de 10. El color de cada sprite está
determinado por su propio registro de color individual.

53287 $ D027 SP0COL


Sprite 0 Color Register (el valor de color predeterminado es 1, blanco)

53288 $ D028 SP1COL


Sprite 1 Color Register (el valor de color predeterminado es 2, rojo)

53289 $ D029 SP2COL


Sprite 2 Color Register (el valor de color predeterminado es 3, cian)

53290 $ D01A SP3COL


Sprite 3 Color Register (el valor de color predeterminado es 4, púrpura)

53291 $ D01B SP4COL


Sprite 4 Color Register (el valor de color predeterminado es 5, verde)

53292 $ D01C SP5COL


Sprite 5 Color Register (el valor de color predeterminado es 6, azul)

53293 $ D01D SP6COL


Sprite 6 Color Register (el valor de color predeterminado es 7, amarillo)

53294 $ D01E SP7COL


Sprite 7 Color Register (el valor de color predeterminado es 12, gris medio)

Rango de ubicación: 53295-53311 ($ D02F- $ D03F)


No conectado

El chip VIC-II tiene solo 47 registros para 64 bytes de


espacio de direcciones posible . Por tanto, las 17 direcciones restantes no acceden a ninguna
memoria. Cuando se leen, siempre darán un valor de 255 ($ FF). Este
valor no cambiará después de escribirles.

Rango de ubicación: 53312-54271 ($ D040- $ D3FF)


Imágenes de registro VIC-II

Dado que el VIC-II solo requiere suficientes líneas de direccionamiento para manejar 64
ubicaciones (el mínimo posible para sus 47 registros), ninguno de los
bits más altos se decodifica al abordar esta área de 1K. El resultado es
que cada área de 64 bytes en este bloque de 1K es un espejo de todos los demás.
POKE53281 + 64,1 tiene el mismo efecto que POKE53281,1 o
POKE53281 + 10 * 64,1; todos convierten el fondo de la pantalla en blanco. En
aras de la claridad de sus programas, es aconsejable utilizar la
dirección base del chip.

54272-54300 $ D400- $ D41C


Registros de dispositivo de interfaz de sonido (SID)

Las ubicaciones de memoria 54272-54300 ($ D400- $ D41C) se utilizan para direccionar el


dispositivo de interfaz de sonido (SID) 6581.

SID es un chip generador de efectos de sonido y sintetizador de música personalizado


que le da al 64 sus impresionantes capacidades musicales. Proporciona
tres canales de música separados, o voces, como se les llama. Cada
voz tiene una resolución de frecuencia de 16 bits, control de forma de onda,
modelado de envolvente , sincronización de oscilador y modulación de anillo. En
adición, de paso alto programable, de paso bajo, y de paso de banda filtros pueden
ser conjunto y habilitado o deshabilitado para cada canal de sonido.

Dado que algunas de estas ubicaciones deben utilizarse en conjunto para


producir sonido,
puede resultar útil un breve resumen de la interacción entre algunos de estos registros.

A menudo, el primer paso es seleccionar un nivel de volumen general usando el


Registro de volumen. Luego, se
elige la frecuencia o el tono deseado de la nota escribiendo en cada uno de los dos bytes que componen el
Registro de frecuencia de 16 bits .

Se debe elegir un ajuste de envolvente ADSR escribiendo valores en el


registro de ataque / caída y sostenido / liberación. Estos determinan la tasa
de subida y bajada del volumen de la nota desde el volumen cero hasta el
volumen máximo y viceversa. Estos ritmos tienen una gran influencia en el
carácter del sonido.

Finalmente, se debe seleccionar la forma de onda y comenzar la nota (o el


oscilador cerrado, como decimos). Esto se hace escribiendo ciertos bits en
el Registro de control. El control de forma de onda le permite seleccionar uno de
cuatro formas de onda diferentes, cada una de las cuales tiene un contenido armónico variable
que afecta la calidad del tono del sonido. Al escribir un 1 en el
bit de puerta, inicia el ciclo Attack / Delay / Sustain. Después de subir a un
pico y bajar al volumen de Sustain, el volumen continuará al
www.unusedino.de/ec64/technical/project64/mapping_c64.html 78/126
25/9/2020 Mapping The C64
mismo nivel hasta que escriba un 0 en el bit de puerta. Entonces,
comenzará el ciclo de lanzamiento. Asegúrese de mantener el mismo bit de forma de onda establecido
en 1 mientras escribe el 0 en el bit de puerta, para que
comience el ciclo de liberación . De lo contrario, el sonido se detendrá por completo, como también lo hará si
el Registro de volumen o el Registro de frecuencia se establece en 0.

Debe tenerse en cuenta que, a excepción de los últimos cuatro registros de chip SID,
estas direcciones son de solo escritura. Eso significa que sus valores no se
pueden determinar haciendo PEEKing en estas ubicaciones.

Rango de ubicación: 54272-54273 ($ D400- $ D401)


Control de frecuencia de voz 1

Juntas, estas dos ubicaciones controlan la frecuencia o el tono de la


salida musical de la voz 1. Se debe seleccionar alguna frecuencia
para que se escuche la voz 1. Esta frecuencia se puede cambiar en medio
de una nota para lograr efectos especiales. El rango de 16 bits del
registro de control de frecuencia cubre más de ocho octavas completas y le permite
variar el tono de 0 (muy bajo) a aproximadamente 4000 Hz (muy alto),
en 65536 pasos. La frecuencia exacta de la salida se puede determinar
mediante la ecuación

FRECUENCIA = (VALOR DE REGISTRO * RELOJ / 16777216) Hz

donde RELOJ es igual a la frecuencia del reloj del sistema, 1022730 para sistemas estadounidenses
(NTSC), 985250 para europeos (PAL) y VALOR DE REGISTRO es el
valor combinado de estos registros de frecuencia. Ese valor combinado
es igual al valor del byte bajo más 256 veces el valor del
byte alto . Utilizando el valor del reloj americano (NTSC), la ecuación resulta
en

FRECUENCIA = VALOR DE REGISTRO * .060959458 Hz

54272 $ D400 FRELO1


Control de frecuencia de voz 1 (byte bajo)

54273 $ D401 FREHI1


Control de frecuencia de voz 1 (byte alto)

Rango de ubicación: 54274 -54275 ($ D402- $ D403)


Control de ancho de forma de onda de pulso de voz 1

Como verá a continuación bajo la descripción del Registro de control en


54276 ($ D404), puede seleccionar una de cuatro formas de onda diferentes para la
salida de cada voz. Si se selecciona la forma de onda del pulso, estos
registros deben configurarse para establecer el ancho del pulso.

El ancho de pulso tiene una resolución de 12 bits, compuesto por el valor en


el primer registro y el valor en el nibble inferior del segundo
registro. El ancho del pulso determina el ciclo de trabajo, o la proporción del
tiempo que la onda rectangular permanecerá en la parte alta del
ciclo.

La siguiente fórmula muestra la relación entre el valor en el


Registro de ancho de pulso y la proporción de tiempo que la onda permanece en
la parte alta del ciclo:

ANCHO DE PULSO = (VALOR DE REGISTRO / 40,95)%

El rango posible de los valores de registro (0-4095) cubre el rango de


los ciclos de trabajo de 0 a 100 por ciento en 4096 pasos. Cambiar el
ancho del pulso cambiará enormemente el sonido creado con la
forma de onda del pulso .

54274 $ D402 PWLO1


Ancho de forma de onda de pulso de voz 1 (byte bajo)

54275 $ D403 PWHI1


Ancho de forma de onda de pulso de voz 1 (nybble alto)

54276 $ D404 VCREG1


Bit de
registro de control de voz 1
0: Bit de puerta: 1 = Iniciar ataque / decaimiento / sostenido, 0 = Iniciar liberación
Bit 1: Sync Bit: 1 = Sincronizar oscilador con frecuencia del oscilador 3
Bit 2: Modulación en anillo: 1 = Modulación en anillo de los osciladores 1 y 3
Bit 3: Bit de prueba: 1 = Deshabilitar el oscilador 1
Bit 4: Seleccionar forma de onda triangular
Bit 5: Seleccionar forma de onda en diente de sierra
Bit 6: Seleccionar forma de onda de pulso
Bit 7: Seleccionar forma de onda de ruido aleatorio

Bit 0. El bit 0 se utiliza para controlar el sonido. Si se establece este bit en 1


mientras se selecciona una de las cuatro formas de onda, se iniciará la parte de
ataque / caída / sostenido del ciclo. Al volver a establecer este bit en 0
(manteniendo la misma configuración de forma de onda) en cualquier momento después de que una nota haya
comenzado a reproducirse, comenzará el ciclo de liberación de la nota. Por supuesto,
para que el bit de puerta tenga efecto, la frecuencia y
Se deben configurar los registros de ataque / decaimiento / sostenido / liberación (ADSR), así como
el ancho de pulso, si es necesario, y el control de volumen establecido en un
valor distinto de cero .

Bit 1. Este bit se utiliza para sincronizar la frecuencia fundamental del


oscilador 1 con la frecuencia fundamental del oscilador 3, lo que
le permite crear una amplia gama de estructuras armónicas complejas a partir de la voz
1. La sincronización se produce cuando este bit se establece en 1. Oscilador 3
debe establecerse en una frecuencia distinta de cero, pero ningún otro
www.unusedino.de/ec64/technical/project64/mapping_c64.html 79/126
25/9/2020 Mapping The C64
parámetro de la voz 3 afectará la salida de la voz 1.

Bit 2. Cuando el bit 2 se establece en 1, la salida de la forma de onda triangular de la voz


1 se reemplaza con una combinación modulada en anillo de Osciladores 1 y
3. Esta modulación en anillo produce estructuras de armónicos no armónicos que
son útiles para crear efectos de campana o gong.

Bit 3. El bit 3 es el bit de prueba. Cuando se establece en 1, desactiva la salida


del oscilador. Esto puede resultar útil para generar
formas de onda muy complejas (incluso síntesis de voz) bajo control de software.

Bit 4. Cuando se establece en 1, el Bit 4 selecciona la salida de forma de onda triangular del
Oscilador 1. El bit 0 también debe establecerse para que suene la nota.

Bit 5. Este bit selecciona la forma de onda de diente de sierra cuando se establece en 1. El bit 0
también debe establecerse para que comience el sonido.

Bit 6. El Bit 6 elige la forma de onda de pulso cuando se establece en 1. El


contenido armónico del sonido producido usando esta forma de onda puede variarse usando el
Registros de ancho de pulso. El bit 0 debe establecerse para comenzar el sonido.

Bit 7. Cuando el bit 7 se establece en 1, se establece la forma de onda de salida de ruido para el
oscilador 1. Esto crea una salida de sonido aleatoria cuya
forma de onda varía con una frecuencia proporcional a la del oscilador
1. Se puede utilizar para imitar el sonido de explosiones, tambores y
otros ruidos no afinados.

Se debe elegir una de las cuatro formas de onda para crear un sonido.
El establecimiento de más de uno de estos bits dará como resultado un AND lógico de
las formas de onda. En particular,
no se recomienda la combinación de la forma de onda de ruido y otra.

Rango de ubicación: 54277-54278 ($ D405- $ D406) Control de envolvente de


voz 1 (ADSR)

Cuando se toca una nota en un instrumento musical, el volumen no


sube repentinamente a un pico y luego se corta a cero. Más bien, el volumen
aumenta hasta un pico, se nivela a un valor intermedio y luego se desvanece
. Esto crea lo que se conoce como envolvente de volumen.

La primera fase de la envolvente, en la que el volumen alcanza un pico,


se conoce como fase de ataque. La segunda, en la que desciende a un
nivel intermedio, se denomina fase de decaimiento. El tercero, en el que
se mantiene el nivel intermedio de volumen, se conoce como
período de sostenimiento . El intervalo final, en el que el sonido se desvanece, se denomina
parte de liberación del ciclo.

El chip SID permite que la envolvente de volumen de cada voz sea


controlados, de modo que se puedan imitar instrumentos específicos o
crear nuevos sonidos. Esto se hace a través de los
registros de ataque / caída y sostenido / liberación . Cada registro dedica cuatro bits (que pueden almacenar un número
del 0 al 15) a cada fase del ciclo. Cuando se activa una nota
escribiendo un 1 en un bit de forma de onda y en el bit 0 del registro de control,
comienza el ciclo de ataque.

El volumen del sonido alcanza un pico durante el período de tiempo


especificado por el nibble alto del registro de ataque / caída. Una vez que
ha alcanzado el volumen máximo, cae al nivel intermedio durante
el período indicado por el nibble bajo del registro de ataque / caída
(esta es la fase de caída). El volumen de este intermedio o sostenido
El nivel se selecciona colocando un valor en el nibble alto del
registro de sostenimiento / liberación. Este nivel de volumen se mantiene hasta que se
escribe un 0 en el bit de puerta del registro de control (dejando el
bit de forma de onda establecido). Cuando eso sucede, comienza la fase de liberación y
el volumen del sonido comienza a disminuir durante el período
indicado por el nibble bajo del registro de sostenido / liberación.

Puede notar que el volumen del sonido no llega a 0 al


final del ciclo de liberación, y es posible que deba apagar el sonido para
eliminar el ruido residual. Puede hacer esto configurando el
bit de forma de onda de nuevo a 0, cambiando la frecuencia a 0 o configurando el
volumen en 0.

54277 $ D405 ATDCY1


Registro de ataque / caída de voz 1

Bits 0-3: Seleccione la duración del ciclo de caída (0-15)


Bits 4-7: Seleccione la duración del ciclo de ataque (0-15) Los

Bits 4-7 controlan la duración del ciclo de ataque. Este es el período


de tiempo durante el cual el volumen aumentará de 0 a su amplitud máxima.
Hay 16 duraciones que se pueden seleccionar. La forma en que el
número colocado aquí corresponde al tiempo transcurrido de este ciclo es la
siguiente:

0 = 2 milisegundos 8 = 100 milisegundos


1 = 8 milisegundos 9 = 250 milisegundos
2 = 16 milisegundos 10 = 500 milisegundos
3 = 24 milisegundos 11 = 800 milisegundos
4 = 38 milisegundos 12 = 1 segundo
5 = 56 milisegundos 13 = 3 segundos
6 = 68 milisegundos 14 = 5 segundos
7 = 80 milisegundos 15 = 8 segundos

Bits 0-3 de control de la longitud de la fase de caída, en la que el volumen de


la nota declinaciones desde el pico alcanzado en la fase de ataque hasta el
nivel de sostenido. El número seleccionado corresponde a la duración de esta
fase como se muestra a continuación:
www.unusedino.de/ec64/technical/project64/mapping_c64.html 80/126
25/9/2020 Mapping The C64

0 = 6 milisegundos 8 = 300 milisegundos


1 = 24 milisegundos 9 = 750 milisegundos
2 = 48 milisegundos 10 = 1.5 segundos
3 = 72 milisegundos 11 = 2.4 segundos
4 = 114 milisegundos 12 = 3 segundos
5 = 168 milisegundos 13 = 9 segundos
6 = 204 milisegundos 14 = 15 segundos
7 = 240 milisegundos 15 = 24 segundos

Dado que las dos funciones comparten un registro, debe multiplicar el


valor de ataque por 16 y agregarlo al valor de caída para obtener
el número que se colocará en el registro:

REGISTRO VALOR = (ATAQUE * 16) +

DECAY 54278 $ D406 SUREL1


Voz 1 Sustain / Release Control Registro

Bits 0-3: Seleccione la duración del ciclo de liberación (0-15)


Bits 4-7: Seleccione el nivel de volumen de sostenido (0 -15) Los

bits 4-7 seleccionan el nivel de volumen en el que se sostiene la nota.


Después del ciclo de caída, el volumen de la salida de la voz 1
permanecerá en el nivel de sostenido seleccionado mientras el bit de puerta del
El registro de control se establece en 1. Los valores de sostenido van de 0, que
elige sin volumen, a 15, que establece la salida de la voz 1 igual al
volumen máximo alcanzado durante el ciclo de ataque.

Los bits 0-3 determinan la duración del ciclo de liberación. Esta fase, en la
que el volumen se desvanece desde el nivel de sostenido hasta un volumen cercano a cero,
comienza cuando el bit de puerta del Registro de control se establece en 0 (
dejando la configuración de forma de onda que se eligió previamente). La
duración de esta disminución de volumen corresponde al número (0-15)
seleccionado de la misma manera que para el valor de disminución:

0 = 6 milisegundos 8 = 300 milisegundos


1 = 24 milisegundos 9 = 750 milisegundos
2 = 48 milisegundos 10 = 1,5 segundos
3 = 72 milisegundos 11 = 2,4 segundos
4 = 114 milisegundos 12 = 3 segundos
5 = 168 milisegundos 13 = 9 segundos
6 = 204 milisegundos 14 = 15 segundos
7 = 240 milisegundos 15 = 24 segundos

Rango de ubicación : 54279-54292 ($ D407- $ D414) Controles de


voz 2 y voz 3

Los diversos registros de control para estas dos voces corresponden casi
exactamente a los de la voz 1. La única excepción es que los
bits de sincronización y modulación de anillo de la voz 2 funcionan en los osciladores 1 y 2, mientras que
los mismos bits del registro de control para la voz 3 usan los osciladores 2
y 3.

54279 $ D407 FRELO2


Control de frecuencia de voz 2 (byte bajo)

54280 $ D408 FREHI2


Control de frecuencia de voz 2 (byte alto)

54281 $ D409 PWLO2


Ancho de forma de onda de pulso de voz 2 (byte bajo)

54282 $ D40A PWHI2


Ancho de forma de onda de pulso de voz 2 (nybble alto)

54283 $ D40B VCREG2


Bit 0 de
registro de control de voz 2
: Bit de puerta: 1 = Iniciar ataque / decaimiento / sostenido, 0 = Iniciar liberación
Bit 1: Bit de sincronización: 1 = Sincronizar oscilador con frecuencia del oscilador 1
Bit 2: Modulación en anillo: 1 = Modular en anillo los osciladores 2 y 1
Bit 3: Bit de prueba: 1 = Deshabilitar oscilador 2
Bit 4: Seleccionar forma de onda triangular
Bit 5: Seleccionar forma de onda de diente de sierra
Bit 6: Seleccionar forma de onda de pulso
Bit 7: Seleccionar forma de onda de ruido

54284 $ D40C ATDCY2


Registro de ataque / caída de voz 2

Bits 0-3: Seleccionar duración del ciclo de caída (0-15)


Bits 4-7: Seleccionar duración del ciclo de ataque (0-15)

54285 $ D40D SUREL2


Voice 2 Sustain / Release Control Register

Bits 0-3: Seleccione la duración del ciclo de liberación (0-15)


Bits 4-7: Seleccione el nivel de volumen de sustain (0-15)

54286 $ D40E FRELO3


Voice 3 Frequency Control (byte bajo )

54287 $ D40F FREHI3


Control de frecuencia de voz 3 (byte alto)

54288 $ D410 PWLO3


Ancho de forma de onda de pulso de voz 3 (byte bajo)
www.unusedino.de/ec64/technical/project64/mapping_c64.html 81/126
25/9/2020 Mapping The C64

54289 $ D411 PWHI3


Ancho de forma de onda de pulso de voz 3 (nybble alto)

54290 $ D412 VCREG3


Registro de control de voz 3

Bit 0: Bit de puerta: 1 = Iniciar ataque / decaimiento / sostenido, 0 = Iniciar liberación


Bit 1: Bit de sincronización: 1 = Sincronizar oscilador con frecuencia del oscilador 2
Bit 2: Modulación en anillo: 1 = Modulación en anillo Osciladores 3 y 2
Bit 3: Bit de prueba: 1 = Deshabilitar oscilador 3
Bit 4: Seleccionar forma de onda triangular
Bit 5: Seleccionar forma de onda de diente de sierra
Bit 6: Seleccionar forma de onda de pulso
Bit 7: Seleccionar forma de onda de ruido

54291 $ D413 ATDCY3 Bits de registro


de ataque / caída de voz 3

0-3: Seleccione la duración del ciclo de caída (0-15)


Bits 4-7: Seleccione la duración del ciclo de ataque (0-15)

54292 $ D414 SUREL3


Voice 3 Sustain / Release Control Register

Bits 0-3: Seleccione la duración del ciclo de release (0-15)


Bits 4-7: Seleccione el nivel de volumen de sustain (0 -15)

Rango de ubicación: 54293-54296 ($ D415- $ D418)


Controles de filtro

Además de los controles detallados anteriormente para cada voz, el


chip SID también proporciona una capacidad de filtrado que le permite
atenuar (hacer más silencioso) ciertos rangos de frecuencias . Se
puede filtrar cualquiera o las tres voces, e incluso existe una disposición para
filtrar una señal externa que se ingresa a través del pin 5 del
conector del monitor.

A low-pass filter is available, which suppresses the volume of those


frequency components that are above a designated cutoff level. The
high-pass filter reduces the volume of frequency components that are
below a certain level. The band-pass filter reduces the volume of
frequency components on both sides of the chosen frequency, thereby
enhancing that frequency. Finally, the high-pass and low-pass filters
can be combined to form a notch reject filter, which reduces the
folume of the frequency components nearest the selected frequency.
These various filters can dramatically change the quality of the sound
produced.

The first two registers are used to select the filter cutoff
frequency. This is the frequency above or below which any sounds will
be made quieter. The further away from this level any frequency
components are, the more their output volume will be suppresed (high-
and low-pass filters reduce the volume of those components by 12 dB
per octave away from the center frequency, while the band-pass filter
attenuates them by 6 dB per octave).

The cutoff frequency has an 11-bit range (which corresponds to the


numbers 0 to 2047). This is made up of a high-byte and three low
bits. Therefore, to compute the frequency represented by the value in
these registers, you must multiply the value in the high byte by 8,
and add the value of the low three bits. The range of cutoff
freqnencies represented by these 2048 values stretches from 30 Hz to
about 12,000 Hz. The exact frequency may be calculated with the
formula:

FREQUENCY=(REGISTER VALUE*5.8)+30Hz

An additional element in filtering is the resonance control. This


allows you to peak the volume of the frequency elements nearest the
cutoff frequency.

54293 $D415 CUTLO

Bits 0-2: Low portion of filter cutoff frequency


Bits 5-7: Unused

54294 $D416 CUTHI


Filter Cutoff Frequency (high byte)

54295 $D417 RESON


Filter Resonance Control Register

Bit 0: Filter the output of voice 1? 1=yes


Bit 1: Filter the output of voice 2? 1=yes
Bit 2: Filter the output of voice 3? 1=yes
Bit 3: Filter the output from the external input? 1=yes
Bits 4-7: Select filter resonance 0-15

Bits 0-3 are used to control which of the voices will be altered by
the filters. If one of these bits is set to 1, the corresponding
voice will be processed through the filter, and its harmonic content
will be changed accordingly. If the bit is set to 0, the voice will
pass directly to the audio output. Note that there is also a
provision for processing an external audio signal which is brought
through pin 5 of the Audio/Video Port.

Bits 4-7 control the resonance of the filter. By placing a number


www.unusedino.de/ec64/technical/project64/mapping_c64.html 82/126
25/9/2020 Mapping The C64
from 0 to 15 in these four bits, you may peak the volume of those
frequencies nearest the cutoff. This creates an even sharper
filtering effect. A setting of 0 causes no resonance, while a setting
of 15 gives maximum resonance.

54296 $D418 SIGVOL


Volume and Filter Select Register

Bits 0-3: Select output volume (0-15)


Bit 4: Select low-pass filter, 1=low-pass on
Bit 5: Select band-pass filter, 1=band-pass on
Bit 6: Select high-pass filter, 1=high-pass on
Bit 7: Disconnect output of voice 4, 1=voice 3 off

Bits 0-3 control the volume of all outputs. The possible volume
levels range from 0 (no volume) to 15 (maximum volume). Some level of
volume must be set here before any sound can be heard.

Bits 4-6 control the selection of the low-pass, band-pass, or


high-pass filter. A 1 in any of these bits turns the corresponding
filter on. These filters can be combined, although only one cutoff
frequency can be chosen. In order for the filter to have any effect,
at least one of the voices must be routed through it using the Filter
Resonance Control Register at 54295 ($D417).

When Bit 7 is set to 1, it disconnects the output of voice 3. This


allows you to use the output of the oscillator for modulating the
frequency of the other voices, or for generating random number,
without any undesired audio output.

Location Range: 54297-54298 ($D419-$D41A)


Game Paddle Inputs

These registers allow you to read the game paddles that plug into
joystick Controller Ports 1 and 2. Each paddle uses a variable
resistor (also known as a potentiometer or pot), whose resistance is
controlled by turning a knob. The varying resistance is used to vary
the voltage to two pins of the SID chip between 0 and +5 volts.
Analog-to-digital (A/D) converters in the chip interpret these voltage
levels as binary values and store the values in these registers.
These registers return a number from 0 (minumum resistance) to 255
(maximum resistance) for each paddle in either of the ports, depending
on the position of the paddle knob.

Since these registers will read the paddle values for only one
controller port, there is a switching mechanism which allows you to
select which of the two ports to read. By writing a bit-pair of 01
(bit value of 64) to the last two bits of CIA #1 Data Port A (56320,
$DC00), you select the paddles on joystick Controller Port 1. By
writing a bit-pair of 10 (bit value of 128), you select the paddles on
Controller Port 2.

If you look at the description of Data Port A (56320, $DC00), however,


you will notice that it is also used in the keyboard scanning process.
By writing to this port, you determine which keyboard column will be
read.

Since the IRQ interrupt keyboard scan routine and the routine that
checks for the STOP key are putting values into this location 60 times
per second, you cannot reliable select the pair of paddles you wish to
read from BASIC without first turning off the keyboard IRQ. This can
be done with a POKE 56333,127. You can then read the paddles with the
statements A=PEEK(54297) and B=PEEK(54298). The IRQ can be restored
after a paddle read with a POKE 56333,129. It may, however, be easier
and more accurate in the long run to use a machine language paddle
read subroutine such as that presented on page 347 of the Commodore 64
Programmer's Reference Guide.

The paddle fire buttons are read as Bits 2 and 3 of the Data Ports A
(56320, $DC00) and B (56321, $DC01). On Port A, if Bit 2 is set to 0,
button 1 is pushed, and if Bit 3 is set to 0, button 2 is pushed. On
Port B, if Bit 2 is set to 0, button 3 is pushed, and if Bit 3 is set
to 0, button 4 is pushed.

The BASIC statements to test these buttons, thereore, are:

PB(1)=(PEEK(56321)AND4)/4
PB(2)=(PEEK(56321)AND8)/8
PB(3)=(PEEK(56320)AND4)/4
PB(4)=(PEEK(56320)AND8)/8

If a 0 is returned by the PEEK statement, the button is pushed, and if


a 1 is returned, it is not.

54297 $D419 POTX


Read Game Paddle 1 (or 3) Position

54298 $D41A POTY


Read Game Paddle 2 (or 4) Position

54299 $D41B RANDOM


Read Oscillator 3/Random Number Generator

This register lets you read the upper eight bits of the waveform
output of Oscillator 3. The kinds of numbers generated by this output
depend on the type of waveform selected.

If the sawtooth waveform is chosen, the output read by this register


www.unusedino.de/ec64/technical/project64/mapping_c64.html 83/126
25/9/2020 Mapping The C64
will be a series of numbers which start at 0 and increase by 1 to a
maximum of 255, at which time they start over at 0.

When the triangle waveform is chosen, they increase from 0 to 255, at


which time they decrease to 0 again. The rate at which these numbers
change is determined by the frequency of Oscillator 3.

If the pulse waveform is selected, the output here will be either 255
or 0.

Finally, selecting the noise waveform will produce a random series of


numbers between 0 and 255. This allows you to use the register as a
random number generator for games.

There are many other uses for reading Oscillator 3, however,


particularly for modulation of the other voices through machine
language software. For example, the output of this register could be
added to the frequency of another voice. If the triangle waveform
were selected for this purpose, it would cause the frequency of the
other voice to rise and fall, at the frequency of Oscillator 3
(perhaps for vibrato effects). This output can also be combined with
the Filter Frequency or Pulse Width Registers to vary the values in
these registers quickly over a short period of time.

Normally, when using Oscillator 3 for modulation, the audio output of


voice 3 should be turned off by setting Bit 7 of the Volume and Filter
Select Register at 54296 ($d418) to 1. It is not necessary to gate
Bit 0 of Control Register 3 to use the oscillator, however, as its
output is not affected by the ADSR envelope cycle.

54300 $D41C ENV3


Envelope Generator 3 Output

This register allows you to read the output of the voice 3 Envelope
generator, in much the same way that the preceding register lets you
read the output of Oscillator 3. This output can also be added to
another oscillator's Frequency Control Registers, Pulse Width
Registers, or the Filter Frequency Control Register. In order to
produce any output from this register, however, the gate bit in
Control Register 3 must be set to 1. Just as in the production of
sound, setting the gate bit to 1 starts the attack/decay/sustain
cycle, and setting it back to 0 starts the release cycle.

Location Range: 54301-54303 ($D41D-$D41F)


Not Connected

The SID chip has been provided with enough addresses for 32 different
registers, but as it has only 29, the remaining three addresses are
not used. Reading them will always return a value of 255 ($FF), and
writing to them will have no effect.

Location Range: 54304-55295 ($D420-$D7FF)


SID Register Images

Since the SID chip requires enough addressing lines for only 32
locations (the minimum possible for its 29 registers), none of the
higher bits are decoded when addressing the 1K area that has been
assigned to it. The result is that every 32-byte area in this 1K
block is a mirror of every other. For the sake of clarity in your
programs, it is advisable not to use these addresses at all.

55296-56319 $D800-$DBFF
Color RAM

The normal Commodore 64 text graphics system uses a screen RAM area to
keep track of the character shapes that are to be displayed. But
since each character can be displayed in any of 16 foreground colors,
there must also be a parallel area which keeps track of the foreground
color. This 1024-byte area is used for that purpose (actually, since
there are only 1000 screen positions, only 1000 byte actually affect
screen color).

These 1000 bytes each control the foreground color of one character,
with the first byte controlling the foreground color of the character
in the upper- left corner, and subsequent bytes controlling the
characters to the right and below that character.

Because only four bits are needed to represent the 16 colors


available, only the low four bits of each Color RAM location are
connected (this is why they are sometimes referred to as Color RAM
Nybbles). Writing to the high bits will not affect them, and these
four bits will usually return a random value when read (a small number
of 64s return a constant value).

Therefore, in order to read Color RAM correctly, you must mask out the
top bits by using the logical AND function. In BASIC, you can read
the first byte of Color RAM with the statement CR=PEEK(55296)AND15.
This will always return a color value between 0 and 15. These color
values correspond to the following colors:

0 = BLACK
1 = WHITE
2 = RED
3 = CYAN (LIGHT BLUE-GREEN)
4 = PURPLE
5 = GREEN
6 = BLUE
7 = YELLOW
www.unusedino.de/ec64/technical/project64/mapping_c64.html 84/126
25/9/2020 Mapping The C64
8 = ORANGE
9 = BROWN
10 = LIGHT RED
11 = DARK GRAY
12 = MEDIUM GRAY
13 = LIGHT GREEN
14 = LIGHT BLUE
15 = LIGHT GRAY

Color mapping affords a convenient method of changing the color of the


text display without changing the letters. By POKEing the appropriate
section of Color RAM, you can change the color of a whole section of
text on the screen without affecting the content of the text. You can
even use this method to make letters disappear by changing their
foreground colors to match the background (or by changing the
background to match the foreground), and later make them reappear by
changing them back, or by changing the background to a contrasting
color. An interesting example program which changes Color RAM quickly
in BASIC can be found under the entry for 648 ($288).

A change in the Operating System causes newer 64s to set all of the
Color RAM locations to the same value as the current background color
whenever the screen is cleared. Therefore, POKEing character codes to
the Screen RAM area will not appear to have any effect, because the
letters will be the same color as the background. This can easily be
turned to your advantage, however, because it means that all you have
to do to set all of Color RAM to a particular value is to set the
background color to that value (using the register at 53281 ($D021)),
clear the screen, and return the background color in the desired
value.

The various garphics modes use this area differently than does the
regular text mode. In high-resolution bitmap mode, this area is not
used at all, but in multicolor bitmap mode it is used to determine the
color of the 11 bit-pair for a given 8 by 8 dot area.

In multicolor text mode, only the lowest three bits are used, so only
colors 0-7 may be selected. The fourth bit is used to determine
whether a character will be displayed in regular text or multicolor
text. Characters with a color value over 7 are displayed as
multicolor characters, with the color of the 11 bit-pair determined by
the color value minus 8. Characters with a color value under 8 are
displayed normally.

It should be noted that unlike the Screen RAM area, which can be moved
to any RAM location, the Color RAM area is fixed, and will function
normally regardless of where screen memory is located.

56320-56335 $DC00-$DC0F
Complex Interface Adapter (CIA) #1 Registers

Locations 56320-56335 ($DC00-$DC0F) are used to communicate with the


Complex Interface Adapter chip #1 (CIA #1). This chip is a successor
to the earlier VIA and PIA devices used on the VIC-20 and PET. This
chip functions the same way as the VIA and PIA: It allows the 6510
microprocessor to communicate with peripheral input and output
devices. The specific devices that CIA #1 reads data from and sends
data to are the joystick controllers, the paddle fire buttons, and the
keyboard.

In addition to its two data ports, CIA #1 has two timers, each of
which can count an interval from a millionth of a second to a
fifteenth of a second. Or the timers can be hooked together to count
much longer intervals. CIA #1 has an interrupt line which is
connected to the 6510 IRQ line. These two timers can be used to
generate interrupts at specified intervals (such as the 1/60 second
interrupt used for keyboard scanning, or the more complexly timed
interrupts that drive the tape read and write routines). As you will
see below, the CIA chip has a host of other features to aid in
Input/Output functions.

Location Range: 56320-56321 ($DC00-$DC01)


CIA #1 Data Ports A and B

These registers are where the actual communication with outside


devices takes place. Bits of data written to these registers can be
sent to external devices, while bits of data that those devices send
can be read here.

The keyboard is so necessary to the computer's operation that you may


have a hard time thinking of it as a peripheral device. Nonetheless,
it cannot be directly read by the 6510 microprocessor. Instead, the
keys are connected in a matrix of eight rows by eight columns to CIA
#1 Ports A and B. The layout of this matrix is shown below.

WRITE TO PORT A READ PORT B (56321, $DC01)


56320/$DC00
Bit 7 Bit 6 Bit 5 Bit 4 Bit 3 Bit 2 Bit 1 Bit 0

Bit 7 STOP Q C= SPACE 2 CTRL <- 1

Bit 6 / ^ = RSHIFT HOME ; * LIRA

Bit 5 , @ : . - L P +

Bit 4 N O K M 0 J I 9

Bit 3 V U H B 8 G Y 7
www.unusedino.de/ec64/technical/project64/mapping_c64.html 85/126
25/9/2020 Mapping The C64

Bit 2 X T F C 6 D R 5

Bit 1 LSHIFT E S Z 4 A W 3

Bit 0 CRSR DN F5 F3 F1 F7 CRSR RT RETURN DELETE

As you can see, there are two keys which do not appear in the matrix.
The SHIFT LOCK key is not read as a separate key, but rather is a
mechanical device which holds the left SHIFT key switch in a closed
position. The RESTORE key is not read like the other keys either. It
is directly connected to the NMI interrupt line of the 6510
microprocessor, and causes an NMI interrupt to occur whenever it is
pressed (not just when it is pressed with the STOP key).

In order to read the individual keys in the matrix, you must first set
Port A for all outputs (255, $FF), and Port B for all inputs (0),
using the Data Direction Registers. Note that this is the default
condition. Next, you must write a 0 in the bit of Data Port A that
corresponds to the column that you wish to read, and a 1 to the bits
that correspond to columns you wish to ignore. You will then be able
to read Data Port B to see which keys in that column are being pushed.

A 0 in any bit position signifies that the key in the corresponding


row of the selected column is being pressed, while a 1 indicates that
the key is not being pressed. A value of 255 ($FF) means that no keys
in that column are being pressed.

Fortunately for us all, an interrupt routine causes the keyboard to be


read, and the results are made available to the Operating System
automatically every 1/60 second. And even when the normal interrupt
routine cannot be used, you can use the Kernal SCNKEY routine at 65439
($FF9F) to read the keyboard.

These same data ports are also used to read the joystick controllers.
Although common sense might lead you to believe that you could read
the joystick that is plugged into the port marked Controller Port 1
from Data Port A, and the second joystick from Data Port B, there is
nothing common about the Commodore 64. Controller Port 1 is read from
Data Port B, and Controller Port 2 is read from CIA #1 Data Port A.

Joysticks consist of five switches, one each for up, down, right, and
left directions, and another for the fire button. The switches are
read like the key switches--if the switch is pressed, the
corresponding bit will read 0, and if it is not pressed, the bit will
be set to 1. From BASIC, you can PEEK the ports and use the AND and
NOT operators to mask the unused bits and inverse the logic for easier
comprehension. For example, to read the joystick in Controller Port
1, you could use the statement:

S1=NOT PEEK(56321)AND15

The meaning of the possible numbers returned are:

0 = none pressed
1 = up
2 = down
4 = left
5 = up left
6 = down left
8 = right
9 = up right
10 = down right

The same technique can be used for joystick 2, by substituting 56320


as the number to PEEK. By the way, the 3 and 7 aren't listed because
they represent impossible combinations like up-down.

To read the fire buttons, you can PEEK the appropriate port and use
the AND operator to mask all but bit 4:

T1=(PEEK(56321)AND16)/16

The above will return a 0 if the button is pressed, and a 1 if it is


not. Substitute location 56320 as the location to PEEK for Trigger
Button 2.

Since CIA #1 Data Port B is used for reading the keyboard as well as
joystick 1, some confusion can result. The routine that checks the
keyboard has no way of telling whether a particular bit was set to 0
by a keypress or one of the joystick switches. For example, if you
plug the joystick into Controller Port 1 and push the stick to the
right, the routine will interpret this as the 2 key being pressed,
because both set the same bit to 0. Likewise, when you read the
joystick, it will register as being pushed to the right if the 2 key
is being pressed.

The problem of mistaking the keyboard for the joystick can be solved
by turning off the keyscan momentarily when reading the stick with a
POKE 56333, 127:POKE 56320,255, and restoring it after the read with a
POKE 56333,129. Sometimes you can use the simpler solution of
clearing the keyboard buffer after reading the joystick, with a POKE
198,0.

The problem of mistaking the joystick for a keypress is much more


difficult--there is no real way to turn off the joystick. Many
commercially available games just use Controller Port 2 to avoid the
conflict. So, if you can't beat them, sit back and press your
www.unusedino.de/ec64/technical/project64/mapping_c64.html 86/126
25/9/2020 Mapping The C64
joystick to the left in order to slow down a program listing (the
keyscan routine thinks that it is the CTRL key).

As if all of the above were not enough, Port A is also used to control
which set of paddles is read by the SID chip, and to read the paddle
fire buttons. Since there are two paddles per joystick Controller
Port, and only two SID registers for reading paddle positions, there
has to be a method for switching the paddle read from joystick Port 1
to joystick Port 2.

When Bit 7 of Port A is set to 1 and Bit 6 is cleared to 0, the SID


registers will read the paddles on Port 1. When Bit 7 is set to 0 and
Bit 6 is set to 1, the paddles on Port 2 are read by the SID chip
registers. Note that this also conflicts with the keyscan routine,
which is constantly writing different values to CIA #1 Data Port A in
order to select the keyboard column to read (most of the time, the
value for the last column is written to this port, which coincides
with the selection of paddles on joystick Port 1). Therefore, in
order to get an accurate reading, you must turn off the keyscan IRQ
and select which joystick port you want to read. See POTX at 54297
($D419), which is the SID register where the paddles are read, for the
exact technique.

Although the SID chip is used to read the paddle settings, the fire
buttons are read at CIA #1 Data Ports A and B. The fire buttons for
the paddles plugged into Controller Port 1 are read at Data Port B
(56321, $DC01), while those for the paddles plugged into Controller
Port 2 are read from Data Port A (56320, $DC00). The fire buttons are
read at Bit 2 and Bit 3 of each port (the same as the joystick left
and joystick right switches), and as usual, the bit will read 0 if the
corresponding button is pushed, and 1 if it is not.

Although only two of the rout paddle values can be read at any one
time, you can always read all four paddle buttons. See the game
paddle input description at 54297 ($D419) for the BASIC statements
used to read these buttons.

Finally, Data Port B can also be used as an output by either Timer A


or B. It is possible to set a mode in which the timers do not cause
an interrupt when they run down (see the descriptions of Control
Registers A and B at 56334-5 ($DC0E-F)). Instead, they cause the
output on Bit 6 or 7 of Data Port B to change. Timer A can be set
either to pulse the output of Bit 6 for one machine cycle, or to
toggle that bit from 1 to 0 or 0 to 1. Timer B can use Bit 7 of this
register for the same purpose.

56320 $DC00 CIAPRA


Data Port Register A

Bit 0: Select to read keyboard column 0


Read joystick 2 up direction
Bit 1: Select to read keyboard column 1
Read joystick 2 down direction
Bit 2: Select to read keyboard column 2
Read joystick 2 left direction
Read paddle 1 fire button
Bit 3: Select to read keyboard column 3
Read joystick 2 right direction
Read paddle 2 fire button
Bit 4: Select to read keyboard column 4
Read joystick 2 fire button
Bit 5: Select to read keyboard column 5
Bit 6: Select to read keyboard column 6
Select to read paddles on Port A or B
Bit 7: Select to read keyboard column 7
Select to read paddles on Port A or B

56321 $DC01 CIAPRB


Data Port Register B

Bit 0: Read keyboard row 0


Read joystick 1 up direction
Bit 1: Read keyboard row 1
Read joystick 1 down direction
Bit 2: Read keyboard row 2
Read joystick 1 left direction
Read paddle 1 fire button
Bit 3: Read keyboard row 3
Read joystick 1 right direction
Read paddle 2 fire button
Bit 4: Read keyboard row 4
Read joystick 1 fire button
Bit 5: Read keyboard row 5
Bit 6: Read keyboard row 6
Toggle or pulse data output for Timer A
Bit 7: Read keyboard row 7
Toggle or pulse data output for Timer B

Location Range: 56322-56323 ($DC02-$DC03)


CIA #1 Data Direction Registers A and B

These Data Direction Registers control the direction of data flow over
Data Ports A and B. Each bit controls the direction of the data on
the corresponding bit of the port. If teh bit of the Direction
Register is set to a 1, the corresponding Data Port bit will be used
for data output. If the bit is set to a 0, the corresponding Data
Port bit will be used for data input. For example, Bit 7 of Data
Direction Register A controls Bit 7 of Data Port A, and if that
www.unusedino.de/ec64/technical/project64/mapping_c64.html 87/126
25/9/2020 Mapping The C64
direction bit is set to 0, Bit 7 of Data Port A will be used for data
input. If the direction bit is set to 1, however, data Bit 7 on Port
A will be used for data output.

The default setting for Data Direction Register A is 255 (all


outputs), and for Data Direction Register B it is 0 (all inputs).
This corresponds to the setting used when reading the keyboard (the
keyboard column number is written to Data Port A, and the row number
is then read in Data Port B).

56322 $DC02 CIDDRA


Data Direction Register A

Bit 0: Select Bit 0 of Data Port A for input or output (0=input, 1=output)
Bit 1: Select Bit 1 of Data Port A for input or output (0=input, 1=output)
Bit 2: Select Bit 2 of Data Port A for input or output (0=input, 1=output)
Bit 3: Select Bit 3 of Data Port A for input or output (0=input, 1=output)
Bit 4: Select Bit 4 of Data Port A for input or output (0=input, 1=output)
Bit 5: Select Bit 5 of Data Port A for input or output (0=input, 1=output)
Bit 6: Select Bit 6 of Data Port A for input or output (0=input, 1=output)
Bit 7: Select Bit 7 of Data Port A for input or output (0=input, 1=output)

56323 $DC03 CIDDRB


Data Direction Register B

Bit 0: Select Bit 0 of Data Port B for input or output (0=input, 1=output)
Bit 1: Select Bit 1 of Data Port B for input or output (0=input, 1=output)
Bit 2: Select Bit 2 of Data Port B for input or output (0=input, 1=output)
Bit 3: Select Bit 3 of Data Port B for input or output (0=input, 1=output)
Bit 4: Select Bit 4 of Data Port B for input or output (0=input, 1=output)
Bit 5: Select Bit 5 of Data Port B for input or output (0=input, 1=output)
Bit 6: Select Bit 6 of Data Port B for input or output (0=input, 1=output)
Bit 7: Select Bit 7 of Data Port B for input or output (0=input, 1=output)

Location Range: 56324-56327 ($DC04-$DC07)


Timers A and B Low and High Bytes

These four timer registers (two for each timer) have different
functions depending on whether you are reading from them or writing to
them. When you read from these registers, you get the present value
of the Timer Counter (which counts down from its initial value to 0).
When you write data to these registers, it is stored in the Timer
Latch, and from there it can be used to load the Timer Counter using
the Force Load bit of Control Register A or B (see 56334-5 ($DC0E-F)
below).

These interval timers can hold a 16-bit number from 0 to 65535, in


normal 6510 low-byte, high-byte format (VALUE=LOW BYTE+256*HIGH BYTE).
Once the Timer Counter is set to an initial value, and the timer is
started, the timer will count down one number every microprocessor
clock cycle. Since the clock speed of the 64 (using the American NTSC
television standard) is 1,022,730 cycles per second, every count takes
approximately a millionth of a second. The formula for calculating
the amount of time it will take for the timer to count down from its
latch value to 0 is:

TIME=LATCH VALUE/CLOCK SPEED

where LATCH VALUE is the value written to the low and high timer
registers (LATCH VALUE=TIMER LOW+256*TIMER HIGH), and CLOCK SPEED is
1,022,370 cycles per second for American (NTSC) standard television
monitors, or 985,250 for European (PAL) monitors.

When Timer Counter A or B gets to 0, it will set Bit 0 or 1 in the


Interrupt Control Register at 56333 ($DC0D). If the timer interrupt
has been enabled (see 56333 ($DC0D)), an IRQ will take place, and the
high bit of the Interrupt Control Register will be set to 1.
Alternately, if the Port B output bit is set, the timer will write
data to Bit 6 or 7 of Port B. After the timer gets to 0, it will
reload the Timer Latch Value, and either stop or count down again,
depending on whether it is in one-shot or continuous mode (determined
by Bit 3 of the Control Register).

Although usually a timer will be used to count the microprocessor


cycles, Timer A can count either the microprocessor clock cycles or
external pulses on the CTN line, which is connected to pin 4 of the
User Port.

Timer B is even more versatile. In addition to these two sources,


Timer B can count the number of times that Timer A goes to 0. By
setting Timer A to count the microprocessor clock, and setting Timer B
to count the number of times that Timer A zeros, you effectively link
the two timers into one 32-bit timer that can count up to 70 minutes
with accuracy within 1/15 second.

In the 64, CIA #1 Timer A is used to generate the interrupt which


drives the routine for reading the keyboard and updating the software
clock. Both Timers A and B are also used for the timing of the
routines that read and write tape data. Normally, Timer A is set for
continuous operation, and latched with a value of 149 in the low byte
and 66 in the high byte, for a total Latch Value of 17045. This means
that it is set to count to 0 every 17045/1022730 seconds, or
approximately 1/60 second.

For tape reads and writes, the tape routines take over the IRQ
vectors. Even though the tape write routines use the on-chip I/O port
at location 1 for the actual data output to the cassette, reading and
writing to the cassette uses both CIA #1 Timer A and Timer B for
www.unusedino.de/ec64/technical/project64/mapping_c64.html 88/126
25/9/2020 Mapping The C64
timing the I/O routines.

56324 $DC04 TIMALO


Timer A (low byte)

56325 $DC05 TIMAHI


Timer A (high byte)

56326 $DC06 TIMBLO


Timer B (low byte)

56327 $DC07 TIMBHI


Timer B (high byte)

Location Range: 56328-56331 ($DC08-$DC0B)


Time of Day Clock (TOD)

In addition to the two general-purpose timers, the 6526 CIA chip has a
special-purpose Time of Day Clock, which keeps time in a format that
humans can understand a little more easily than microseconds.

This Time of Day Clock even has an alarm, which can cause an interrupt
at a specific time. It is organized in four registers, one each for
hours, minutes, seconds, and tenths of seconds. Each register reads
out in Binary Coded Decimal (BCD) format, for easier conversion to
ASCII digits. A BCD byte is divided into two nybbles, each of which
represents a single digit in base 10. Even though a four-bit nybble
can hold a number from 0 to 15, only the base 10 digits of 0-9 are
used. Therefore, 10 0'clock would be represented by a byte in the
hours register with the nybbles 0001 and 0000, which stand for the
digits 1 and 0. The binary value of this byte would be 16 (16 times
the high nybble plus the low nybble). Each of the other registers
operates in the same manner. In addition, Bit 7 of the hours register
is used as an AM/PM flag. If that bit is set to 1, it indicates PM,
and if it is set to 0, the time is AM.

The Time of Day Clock Registers can be used for two purposes,
depending on whether you are reading them or writing to them. If you
are reading them, you will always be reading the time. There is a
latching feature associated with reading the hours register in order
to solve the problem of the time changing while you are reading the
registers. For example, if you were reading the hours register just
as the time was changing from 10:59 to 11:00, it is possible that you
would read the 10 in the hours register, and by the time you read the
minutes register it would have changed from 59 to 00. Therefore, you
would read 10:00 instead of either 10:59 or 11:00.

To prevent this kind of mistake, the Time of Day Clock Registers stop
updating as soon as you read the hours register, and do not start
again until you read the tenths of seconds register. Of course, the
clock continues to keep time internally even though it does not update
the registers. If you want to read only minutes, or seconds or tenths
of seconds, there is no problem, and no latching will occur. But
anytime you read hours, you must follow it by reading tenths of
seconds, even if you don't care about them, or else the registers will
not continue to update.

Writing to these registers either sets the time or the alarm,


depending on the setting of Bit 7 of Control Register B (56335,
$DC0F). If that bit is set to 1, writing to the Time of Day registers
sets the alarm. If the bit is set to 0, writing to the Time of Day
registers sets the Time of Day clock. In either case, as with reading
the registers, there is a latch function. This function stops the
clock from updating when you write to the hours register. The clock
will not start again until you write to the tenths of seconds
registers.

The only apparent use of the Time of Day Clock by the 64's Operating
System is in the BASIC RND statement. There, the seconds and tenths
of seconds registers are read and their values used as part of the
seed value for the RND(0) command.

Nonetheless, this clock can be an invaluable resource for the 64 user.


It will keep time more accurately than the software clock maintained
at locations 60-162 ($A0-$A2) by the Timer A interrupt routine. And
unlike that software clock, the Time of Day Clock will not be
disturbed when I/O operations disrupt the Timer A IRQ, or when the IRQ
vector is diverted elsewhere. Not even a cold start RESET will
disrupt the time. For game timers, just set the time for 00:00:00:0
and it will keep track of elapsed time in hours, minutes, seconds and
tenths of seconds format.

The following digital clock program, written in BASIC, will


demonstrate the use of these timers:

10 PRINT CHR$(147):GOSUB 200


20 H=PEEK(56331):POKE 1238,(H AND 16)/16+48:POKE 1239,(H AND 15)+48
30 M=PEEK(56330):POKE 1241,(M AND 240)/16+48:POKE 1242,(M AND 15)+48
40 S=PEEK(56329):POKE 1244,(S AND 240)/16+48:POKE 1245,(S AND 15)+48
50 T=PEEK(56328)AND15:POKE 1247,T+48:GOTO 20
200 INPUT"WHAT IS THE HOUR";H$:IF H$="" THEN 200
210 H=0:IF LEN(H$)>1 THEN H=16
220 HH=VAL(RIGHT$(H$,1)):H=H+HH:POKE56331,H
230 INPUT "WHAT IS THE MINUTE";M$:IF M$=""THEN 200
240 M=0:IF LEN(M$)>1 THEN M=16*VAL(LEFT$(M$,1))
250 MM=VAL(RIGHT$(M$,1)):M=M+MM:POKE56330,M
260 INPUT "WHAT IS THE SECOND";S$:IF S$=""THEN 200
270 S=0:IF LEN(S$)>1 THEN S=16*VAL(LEFT$(S$,1))
www.unusedino.de/ec64/technical/project64/mapping_c64.html 89/126
25/9/2020 Mapping The C64
280 SS=VAL(RIGHT$(S$,1)):S=S+SS:POKE56329,S:POKE56328,0
290 POKE 53281,1:PRINT CHR$(147):POKE 53281,6
300 POKE 1240,58:POKE 1243,58:POKE 1246,58:GOTO 20

56328 $DC08 TODTEN


Time of Day Clock Tenths of Seconds

Bits 0-3: Time of Day tenths of second digit (BCD)


Bits 4-7: Unused

56329 $DC09 TODSEC


Time of Day Clock Seconds

Bits 0-3: Second digit of Time of Day seconds (BCD)


Bits 4-6: First digit of Time of Day seconds (BCD)
Bit 7: Unused

56330 $DC0A TODMIN


Time of Day Clock Minutes

Bits 0-3: Second digit of Time of Day minutes (BCD)


Bits 4-6: First digit of Time of Day minutes (BCD)
Bit 7: Unused

56331 $DC0B TODHRS


Time of Day Clock Hours

Bits 0-3: Second digit of Time of Day hours (BCD)


Bit 4: First digit of Time of Day hours (BCD)
Bits 5-6: Unused
Bit 7: AM/PM Flag (1=PM, 0=AM)

56332 $DC0C CIASDR


Serial Data Port

The CIA chip has an on-chip serial port, which allows you to send or
receive a byte of data one bit at a time, with the most significant
bit (Bit 7) being transferred first. Control Register A at 56334
($DC0E) allows you to choose input or output modes. In input mode, a
bit of data is read from the SP line (pin 5 of the User Port) whenever
a signal on the CNT line (pin 4) appears to let you know that it is
time for a read. After eight bits are received this way, the data is
placed in the Serial Port Register, and an interrupt is generated to
let you know that the register should be read.

In output mode, you write data to the Serial Port Register, and it is
sent out over the SP line (pin 5 of the User Port), using Timer A for
the baud rate generator. Whenever a byte of data is written to this
register, transmission will start as long as Timer A is running and in
continuous mode. Data is sent at half the Timer A rage, and an output
will appear on the CNT line (pin 4 of the User Port) whenever a bit is
sent. After all eight bits have been sent, an interrupt is generated
to indicate that it is time to load the next byte to send into the
Serial Register.

The Serial Data Register is not used by the 64, which does all of its
serial I/O through the regular data ports.

56333 $DC0D CIAICR


Interrupt Control Register

Bit 0: Read / did Timer A count down to 0? (1=yes)


Write/ enable or disable Timer A interrupt (1=enable, 0=disable)
Bit 1: Read / did Timer B count down to 0? (1=yes)
Write/ enable or disable Timer B interrupt (1=enable, 0=disable)
Bit 2: Read / did Time of Day Clock reach the alarm time? (1=yes)
Write/ enable or disable TOD clock alarm interrupt (1=enable,
0=disable)
Bit 3: Read / did the serial shift register finish a byte? (1=yes)
Write/ enable or disable serial shift register interrupt (1=enable,
0=disable)
Bit 4: Read / was a signal sent on the flag line? (1=yes)
Write/ enable or disable FLAG line interrupt (1=enable, 0=disable)
Bit 5: Not used
Bit 6: Not used
Bit 7: Read / did any CIA #1 source cause an interrupt? (1=yes)
Write/ set or clear bits of this register (1=bits written with 1 will
be set, 0=bits written with 1 will be cleared)

This register is used to control the five interrupt sources on the


6526 CIA chip. These sources are Timer A, Timer B, the Time of Day
Clock, the Serial Register, and the FLAG line. Timers A and B cause
an interrupt when they count down to 0. The Time of Day Clock
generates an interrupt when it reaches the ALARM time. The Serial
Shift Register interrupts when it compiles eight bits of input or
output. An external signal pulling the CIA hardware line called FLAG
low will also cause an interrupt (on CIA #1, this FLAG line is
connected to the Cassette Read line of the Cassette Port).

Even if the condition for a particular interrupt is satisfied, the


interrupt must still be enabled for an IRQ actually to occur. This is
done by writing to the Interrupt Control Register. What happens when
you write to this register depends on the way that you set Bit 7. If
you set it to 0, any other bit that was written to with a 1 will be
cleared, and the corresponding interrupt will be disabled. If you set
Bit 7 to 1, any bit written to with a 1 will be set, and the
corresponding interrupt will be enabled. In either case, the
interrupt enable flags for those bits written to with a 0 will not be
www.unusedino.de/ec64/technical/project64/mapping_c64.html 90/126
25/9/2020 Mapping The C64
affected.

For example, in order to disable all interrupts from BASIC, you could
POKE 56333, 127. This sets Bit 7 to 0, which clears all of the other
bits, since they are all written with 1's. Don't try this from BASIC
immediate mode, as it will turn off Timer A which causes the IRQ for
reading the keyboard, so that it will in effect turn off the keyboard.

To turn on the Timer A interrupt, a program could POKE 56333,129. Bit


7 is set to 1 and so is Bit 0, so the interrupt which corresponds to
Bit 0 (Timer A) is enabled.

When you read this register, you can tell if any of the conditions for
a CIA Interrupt were satisfied because the corresponding bit will be
set to a 1. For example, if Timer A counts down to 0, Bit 0 of this
register will be set to 1. If, in addition, the mask bit that
corresponds to that interrupt source is set to 1, and an interrupt
occurs, Bit 7 will also be set. This allows a multi-interrupt system
to read one bit and see if the source of a particular interrupt was
CIA #1. You should note, however, that reading this register clears
it, so you should preserve its contents in RAM if you want to test
more than one bit.

56334 $DC0E CIACRA


Control Register A

Bit 0: Start Timer A (1=start, 0=stop)


Bit 1: Select Timer A output on Port B (1=Timer A output appears on Bit 6 of
Port B)
Bit 2: Port B output mode (1=toggle Bit 6, 0=pulse Bit 6 for one cycle)
Bit 3: Timer A run mode (1=one-shot, 0=continuous)
Bit 4: Force latched value to be loaded to Timer A counter (1=force load
strobe)
Bit 5: Timer A input mode (1=count microprocessor cycles, 0=count signals on
CNT line at pin 4 of User Port)
Bit 6: Serial Port (56332, $DC0C) mode (1=output, 0=input)
Bit 7: Time of Day Clock frequency (1=50 Hz required on TOD pin, 0=60 Hz)

Bits 0-3. This nybble controls Timer A. Bit 0 is set to 1 to start


the timer counting down, and set to 0 to stop it. Bit 3 sets the
timer for one-shot or continuous mode.

In one-shot mode, the timer counts down to 0, sets the counter value
back to the latch value, and then sets Bit 0 back to 0 to stop the
timer. In continuous mode, it reloads the latch value and starts all
over again.

Bits 1 and 2 allow you to send a signal on Bit 6 of Data Port B when
the timer counts. Setting Bit 1 to 1 forces this output (which
overrides the Data Direction Register B Bit 6, and the normal Data
Port B value). Bit 2 allows you to choose the form this output to Bit
6 of Data Port B will take. Setting Bit 2 to a value of 1 will cause
Bit 6 to toggle to the opposite value when the timer runs down (a
value of 1 will change to 0, and a value of 0 will change to 1).
Setting Bit 2 to a value of 0 will cause a single pulse of a one
machine-cycle duration (about a millionth of a second) to occur.

Bit 4. This bit is used to load the Timer A counter with the value
that was previously written to the Timer Low and High Byte Registers.
Writing a 1 to this bit will force the load (although there is no data
stored here, and the bit has no significance on a read).

Bit 5. Bit 5 is used to control just what it is Timer A is counting.


If this bit is set to 1, it counts the microprocessor machine cycles
(which occur at the rate of 1,022,730 cycles per second). If the bit
is set to 0, the timer counts pulses on the CNT line, which is
connected to pin 4 of the User Port. This allows you to use the CIA
as a frequency counter or an event counter, or to measure pulse width
or delay times of external signals.

Bit 6. Whether the Serial Port Register is currently inputting or


outputting data (see the entry for that register at 56332 ($DC0C) for
more information) is controlled by this bit.

Bit 7. This bit allows you to select from software whether the Time
of Day Clock will use a 50 Hz or 60 Hz signal on the TOD pin in order
to keep accurate time (the 64 uses a 60 Hz signal on that pin).

56335 $DC0F CIACRB


Control Register B

Bit 0: Start Timer B (1=start, 0=stop)


Bit 1: Select Timer B output on Port B (1=Timer B output appears on
Bit 7 of Port B)
Bit 2: Port B output mode (1=toggle Bit 7, 0=pulse Bit 7 for one
cycle)
Bit 3: Timer B run mode (1=one-shot, 0=continuous)
Bit 4: Force latched value to be loaded to Timer B counter (1=force
load strobe)
Bits 5-6: Timer B input mode
00 = Timer B counts microprocessor cycles
01 = Count signals on CNT line at pin 4 of User Port
10 = Count each time that Timer A counts down to 0
11 = Count Timer A 0's when CNT pulses are also present
Bit 7: Select Time of Day write (0=writing to TOD registers sets
alarm, 1=writing to TOD registers sets clock)

Bits 0-3. This nybble performs the same functions for Timer B that
www.unusedino.de/ec64/technical/project64/mapping_c64.html 91/126
25/9/2020 Mapping The C64
Bits 0-3 of Control Register A perform for Timer A, except that Timer
B output on Data Port B appears at Bit 7, and not Bit 6.

Bits 5 and 6. These two bits are used to select what Timer B counts.
If both bits are set to 0, Timer B counts the microprocessor machine
cycles (which occur at the rate of 1,022,730 cycles per second). If
Bit 6 is set to 0 and Bit 5 is set to 1, Timer B counts pulses on the
CNT line, which is connected to pin 4 of the User Port. If Bit 6 is
set to 1 and Bit 5 is set to 0, Timer B counts Timer A underflow
pulses, which is to say that it counts the number of times that Timer
A counts down to 0. This is used to link the two numbers into one
32-bit timer that can count up to 70 minutes with accuracy to within
1/15 second. Finally, if both bits are set to 1, Timer B counts the
number of times that Timer A counts down to 0 and there is a signal on
the CNT line (pin 4 of the User Port).

Bit 7. Bit 7 controls what happens when you write to the Time of Day
registers. If this bit is set to 1, writing to the TOD registers sets
the ALARM time. If this bit is cleared to 0, writing to the TOD
registers sets the TOD clock.

Location Range: 56336-56575 ($DC10-$DCFF)


CIA #1 Register Images

Since the CIA chip requires only enough addressing lines to handle 16
registers, none of the higher bits are decoded when addressing the
256-byte area that has been assigned to it. The result is that every
16-byte area in this 256-byte block is a mirror of every other. Even
so, for the sake of clarity in your programs it is advisable to use
the base address of the chip, and not use the higher addresses to
communicate with the chip.

56576-56591 $DD00-$DD0F
Complex Interface Adapter (CIA) #2 Registers

Locations 56576-56591 ($DD00-$DD0F) are used to address the Complex


Interface Adapter chip #2 (CIA #2). Since the chip itself is
identical to CIA #1, which is addressed at 56320 ($DC00), the
discussion here will be limited to the use which the 64 makes of this
particular chip. For more general information on the chip registers,
please see the corresponding entries for CIA #1.

One of the significant differences between CIA chips #1 and #1 is the


use to which Data Ports A and B are put. The peripheral input and
output devices that CIA #2 controls are those on the Serial Bus (such
as the 1541 Disk Drive and 1525 printer), the RS-232 device (which is
used for telecommunications), and the User Port, an eight-bit parallel
port that can be turned to whatever purpose the user desires. In
addition, Data Port A has the important task of selecting the 16K bank
ofmemory that will be used by the VIC-II chip for graphics.

Another significant difference between CIA chips #1 and #2 is that the


interrupt line of CIA #1 is wired to the 6510 IRQ line, while that of
CIA #2 is wired to the NMI line. This means that interrupts from this
chip cannot be masked by setting the Interrupt disable flag (SEI).
They can be disabled from CIA's Mask Register, though. Be sure to use
the NMI vector when setting up routines to be driven by interrupts
generated by this chip.

Location Range: 56576-56577 ($DD00-$DD01)


CIA #2 Data Ports A and B

These registers are where the communication with the Serial Bus,
RS-232 device, and User Port take place. The Serial Bus is like the
IEEE bus which is used by the PET, in that it allows more than one
device to be connected to the port at a time, in a daisychain
arrangement. Since each byte of data is sent one bit at a time,
however, the Serial Bus is at least eight times slower than the IEEE.
It is presently used to control the 1541 Disk Drive and 1525 printer,
and other devices (such as printer interface for Centronics- type
parallel pritners and stringy floppy wafer tape storage units) can be
placed on this bus.

Data Port A is used for communication with the Serial Bus. Bits 5 and
7 are used for Serial Bus Data Output and Input, respectively, and
Bits 4 and 6 are used for the Serial Bus Clock Pulse Output and Input.
Bit 3 of Data Port A is used to send the ATN signal on the Serial Bus.

The 64 has built-in software to handle RS-232 communications through a


modem or other device plugged in the RS-232/User Port. The RS-232
device uses Bit 2 of Data Port A for data output (it is the only line
from Port A that is connected to the RS-232/User Port jack). It also
makes heavy use of Port B, using Bit 7 for the Data Set Ready (DSR)
signal, Bit 6 for the Clear to Send (CTS), Bit 4 for the Carrier
Detect (DCD), Bit 3 for the Ring Indicator (RI), Bit 2 for Data
Terminal Ready (DTR), Bit 1 for Request to Send (RTS), and Bit 0 for
data input. See locations 659-660 ($293-$294) for more details on the
RS-232 device.

All of the data lines which the RS-232 device uses are also available
to the user as part of the User Port. All of the Port B data lines,
and Bit 2 of Port A, are brought out to the User Port connector on the
back of the 64. These data bits are utilized in the normal way: The
port connections are made to TTL-level input or output devices, and
the direction of data is determined by the Data Direction Registers.

In addition, the User Port has pins connected to the two CIA Serial
Ports (whose eight-bit shift registers are well-suited for
www.unusedino.de/ec64/technical/project64/mapping_c64.html 92/126
25/9/2020 Mapping The C64
serial-to-parallel and parallel-to-serial conversion),and the two CNT
lines which aid in the operation of the Serial Ports. The CNT lines
can also be used in conjunction with the CIA Timers, and allow them to
be used as frequency counters, event counters, interval timers, etc.
The advanced features of the CIA chip make almost any type of
interfacing application possible, and in the near future we will
probably see many interesting applications for the User Port on the
64. A pin description of tthe User Port connector is provided below:

User RS-232
Port CIA DB-25
Pin Line Pin Description

1 Ground
2 +5 Volts (100 milliamps maximum)
3 RESET (grounding this pin causes a cold start)
4 CNT1 CIA #1 Serial Port and Timer Counter
5 SP1 CIA #1 Serial Data Port
6 CNT2 CIA #2 Serial Port and Timer Counter
7 SP2 CIA #2 Serial Data Port
8 PC2 CIA #2 handshaking line
9 Connected to the ATN line of the Serial Bus
10 9 Volts AC (+ phase, 50 milliamps maximum)
11 9 volts AC (- phase, 50 milliamps maximum)
12 Ground
A 1 Ground
B FLAG2 CIA #2 handshaking line
C PB0 3 Port B Bit 0--RS-232 Received Data (SIN)
D PB1 4 Port B Bit 1--RS-232 Request to Send (RTS)
E PB2 20 Port B Bit 2--RS-232 Data Terminal Ready (DTR)
F PB3 22 Port B Bit 3--RS-232 Ring Indicator (RI)
H PB4 8 Port B Bit 4--RS-232 Carrier Detect (DCD)
J PB5 Port B Bit 5
K PB6 5 Port B Bit 6--RS-232 Clear to Send (CTS)
L PB7 6 Port B Bit 7--RS-232 Data Set Ready (DSR)
M PA2 2 Port A Bit 2--RS-232 Transmitted Data (Sout)
N 7 Ground

One of the handshaking lines on the above chart, PC2, was not covered
in the discussion of CIA #1, because that line of CIA #1 is not
connected to anything. The CIA #2 PC line is accessible from the User
Port, however. This line will go low for one cycle following a read
or write of Port B on CIA #2. This signal lets external devices know
when data has been read or written.

Bits 0 and 1 of CIA #2 Port A have an extremely important function.


As mentioned in the section on the VIC-II chip (53248, $D000), the
video chip can address only 16K of memory at a time, and all graphics
data must be stored in that 16K block in order to be displayed.
Within this area, sprite graphics data may be placed in any of 256
groups of 64 bytes each. Character data can be stored in any of eight
2K blocks. Text screen memory may be in any of 16 1K areas, and
bitmap screen memory may be in either of two 8K sections.

When you turn the power on, the VIC-II uses the bottom 16K of memory
for graphics. Unfortunately, this block of memory is also used
extensively for other important purposes. Though some means of
eliminating these conflicts are discussed above, in many situations
you will want to change from the default 16K bank at the low end of
memory.

Bits 0 and 1 select the current 16K bank for video memory from the
four possible choices using the following bit patterns:

00 (bit value of 0) Bank 3 (49152-65535, $C000-$FFFF)


01 (bit value of 1) Bank 2 (32768-49151, $8000-$BFFF)
10 (bit value of 2) Bank 1 (16384-32767, $4000-$7FFF)
11 (bit value of 3) Bank 0 (0-16383, $0-$3FFF)

The technique for making this change from BASIC is discussed below.
But before we go ahead and start changing banks, let's briefly review
the contents of these areas, and the considerations for using them for
graphics.

Block 0. This is normally used for system variables and BASIC program
text. Locations 1024-2047 ($400-$7FF) are reserved for the default
position of screen memory.

There is an addition limitation on memory usage of this block, as the


VIC-II sees the character generator ROM at 4096-8191 ($1000-$1FFF),
making this portion of memory unavailable for other graphics data.
Generally, there is little free space here for graphics display data.
Locations 679-767 ($2A7- $2FF) are unused, and could hold one sprite
shape (number 11) or data for 11 characters. The area from 820-1023
($334-$3FF), which includes the cassette I/O buffer, is available for
graphics memory, and is large enough to hold three sprite shapes
(numbers 13, 14, and 15), or data for 25 characters (numbers 103-127).
But getting enough memory for bitmap graphics requires that you either
reserve memory after the end of BASIC text by lowering the end of
BASIC pointer at 56 ($38), or raise the start of BASIC pointer at 44
($2C). See the entries for these pointers for more details.

Block 1. Block 1 is normally used for BASIC program storage. When


using this bank, the VIC-II does not have access to the character
generator ROM. Providing that you lower the top of memory so that
BASIC programs do not interfere, this area is wide open for sprite
shapes, character graphics, and bitmap graphics.

www.unusedino.de/ec64/technical/project64/mapping_c64.html 93/126
25/9/2020 Mapping The C64
The drawbacks to useing this bank are the unavailability of the
character ROM and the limitation on BASIC program space (as little as
14K). The absence of the character ROM is a relatively minor
nuisance, because you can always switch in the ROM and copy any or all
of the characters to RAM (see the entries for location 1 and the
alternate entry for 53248 ($D000), the Character ROM, for details).
This block may be a good alternate choice to avoid potential conflicts
with other applications that use higher memory.

Block 2. The third block (Block 2) consists of 8K of RAM, half of


which is seen by the VIC-II chip as character ROM, and the 8K BASIC
interpreter ROM. The BASIC ROM area is available for graphics. This
is possible because of the 64's special addressing. The VIC-II chip
reads only from RAM, and thus sees the RAM underneath the BASIC ROM,
even if the 6510 has ROM switched in. The 6510, on the other hand,
always writes to RAM, even when dealing with memory it reads as ROM.
Whatever is written to the RAM underlying the BASIC ROM is displayed
normally by the VIC-II chip. This opens up an extra 8K are for
sprites and character data under the BASIC ROM.

You should keep in mind that while you can write to this area, you
cannot read it from BASIC. This may not be a serious problem when it
comes to character sets and sprite data, but it's more of a drawback
if you want to use this RAM for screen memory.

For example, the Operating System has to read the text screen to move
the cursor properly, and if it reads the ROM value instead of the RAM
screen data, it gets hopelessly confused, making it impossible to type
in any commands.

Likewise, you would not be able to read the high-resolution screen if


it were placed here, without some machine language trickery. With
locations 36863-40959 ousted by the character ROM, only 4K of true RAM
remains for use as screen memory, not enough for a complete
high-resolution screen. Therefore, this block is not recommended for
use in bitmap mode if your program needs to check the screen.
Otherwise, this is a good place for graphics memory, particularly if
you need to emulate the screen configuration of the PET.

Block 3. Normally Block 3 contains 4K of RAM that is completely


unused by the system, 4K if I/O registers, and the 8K Operating System
Kernal ROM. It is very convenient to use when you need a lot of
memory space for both graphics and a BASIC program. Although the
character ROM is not available, it can be copied to RAM. The area
under the Kernal ROM can be used as explained above. One possible
conflict that you should be aware of is that the current version of
the DOS support program is written to reside at 52224 ($CC00). It
would be safest to avoid using 52224-53247 for graphics if you plan to
use DOS support.

Changing banks. Once you have selected a bank of 16K to use, the
procedure for making the change from BASIC is as follows:

1. Set the Data Direction Register if necessary. In order to use


Bits 0 and 1 of Port A to change banks, these bits must be set as
outputs in Data Direction Register A. Since this is the default
condition on powering-up, this step normally will not be needed.

2. Select a bank. Banks 0-3 can be chosen by entering the following


lines:

POKE 56578,PEEK(56578) OR 3: REM SET FOR OUTPUT IF NOT ALREADY


POKE 56576,(PEEK(56576) AND 252) OR (3-BANK): REM BANK IS BANK #, MUST
BE 0-3

3. Set the VIC-II register for character memory. As explained at the


entry for location 53272 ($D018), the formula for this is:

POKE 53272,(PEEK(53272) AND 240) OR TK: REM TK IS 2 KBYTE OFFSET FROM


BEGINNING OF BLOCK

4. Set the VIC-II register for display memory. As explained at the


entry for location 53272 ($D018), the formula for this is:

POKE 53272,(PEEK(53272) AND 15) OR K*16: REM K IS KBYTE OFFSET FROM


BEGINNING OF BLOCK

Since steps 3 and 4 operate on the same register, you could combine
these steps and just POKE 53272,(16*K+TK).

5. Set the Operating System pointer for display memory at 648 ($288).
Even though you have just told the VIC-II chip where to display memory
for the screen, the Operating System does not yet know where to write
its text characters. Let it know with this statement:

POKE 648,AD/256: REM AD IS THE ACTUAL ADDRESS OF SCREEN MEMORY

After you make this change, you must watch out for the STOP/RESTORE
key combination. The BRK initialization changes the screen display
default to location 1024 in Bank 0, but not the Operating System
pointer at 648 ($288). As a result, what you are typing will not be
displayed on the screen. The computer will lock up until you turn the
power off and back on again. The simplest way to avoid this problem
is to disable the RESTORE key entirely (see the entries for 792 ($318)
and 808 ($328) for more information).

Below is a sample program which switches to Bank 3. It includes a


machine language transfer routine to move the ROM character set to
www.unusedino.de/ec64/technical/project64/mapping_c64.html 94/126
25/9/2020 Mapping The C64
RAM, and a short interrupt routine to correct the RESTORE key problem.
After the switch is made, a loop isused to POKE characters into the
new screen memory area. Next, the character data is slowly erased, to
show that the character set is now in RAM. Then, a loop is used to
read the locations of the character set, and write to the same
locations. This demonstrates that the 6510 reads the Kernal ROM when
you PEEK those locations, but POKEs to the RAM which is being
displayed. Finally, the machine language move is used again to show
how quickly the set is restored.

20 FOR I=1 TO 33:READ A:POKE 49152+I,A:NEXT: REM SET UP ML ROUTINE


30 GOSUB 200: REM ML COPY OF ROM CHARACTER SET TO RAM
40 POKE 56576,PEEK(56576) AND 252: REM STEP 1, ENABLE BANK 3
50 POKE 53272,44: REM STEPS 2-3, POINT VIC-II TO SCREEN AND CHARACTER MEMORY
60 REM SCREEN OFFSET IS 2*16, CHARACTER OFFSET IS 12
70 POKE 648,200: REM STEP 4, POINT OS TO SCREEN AT 51200 (200*256)
80 PRINT CHR$(147): REM CLEAR SCREEN
90 FOR I=53236 TO 53245:READ A:POKE I,A:NEXT: REM NEW INTERRUPT ROUTINE
100 POKE 53246,PEEK(792):POKE 53247,PEK(793): REM SAVE OLD NMI VECTOR
110 POKE 792,244:POKE 793,207: REM ROUTE THE INTERRUPT THROUGH THE NEW ROUTINE
120 FOR I=0 TO 255:POKE 51400+I,I:POKE 55496+I,1:NEXT
125 REM POKE CHARACTERS TO SCREEN
130 FOR J=1 TO 8:FOR I=61439+J TO I+2048 STEP 8
140 POKE I,0:NEXT I,J: REM ERASE CHARACTER SET
150 FOR I=61440 TO I+2048:POKE I,PEEK(I):NEXT: REM POKE ROM TO RAM
160 GOSUB 200:END: REM RESTORE CHARACTER SET
200 POKE 56334,PEEK(56334) AND 254: REM DISABLE INTERRUPTS
210 POKE 1,PEEK(1) AND 251:REM SWITCH CHARACTER ROM INTO 6510 MEMORY
220 SYS 49152: REM COPY ROM CHARACTER SET TO RAM AT 61440
230 POKE 1,PEEK(1) OR 4: REM SWITCH CHARACTER ROM OUT OF 6510 MEMORY
240 POKE 56334,PEEK(56334)OR 1: REM ENABLE INTERRUPTS
250 RETURN
300 REM DATA FOR ML PROGRAM TO COPY CHARACTER SET TO RAM
310 DATA169,0,133,251,133,253,169,208,133,252,169,240,133,254,162,16
320 DATA160,0,177,251,145,253,136,208,249,230,252,230,254,202,208,240,96
330 REM NEXT IS ML PROGRAM TO MAKE THE RESTORE KEY RESET OS POINTER TO SCREEN
340 DATA 72,169,4,141,136,02,104,108,254,207

See also the sample program showing how to configure your 64 like a
PET at location 43 ($2B).

56576 $DD00 CI2PRA


Data Port Register A

Bits 0-1: Select the 16K VIC-II chip memory bank (11=bank 0, 00=bank 3)
Bit 2: RS-232 data output (Sout)/Pin M of User Port
Bit 3: Serial bus ATN signal output
Bit 4: Serial bus clock pulse output
Bit 5: Serial bus data output
Bit 6: Serial bus clock pulse input
Bit 7: Serial bus data input

56577 $DD01 CI2PRB


Data Port B

Bit 0: RS-232 data input (SIN)/ Pin C of User Port


Bit 1: RS-232 request to send (RTS)/ Pin D of User Port
Bit 2: RS-232 data terminal ready (DTR)/ Pin E of User Port
Bit 3: RS-232 ring indicator (RI)/ Pin F of User Port
Bit 4: RS-232 carrier detect (DCD)/ Pin H of User Port
Bit 5: Pin J of User Port
Bit 6: RS-232 clear to send (CTS)/ Pin K of User Port
Toggle or pulse data output for Timer A
Bit 7: RS-232 data set ready (DSR)/ Pin L of User Port
Toggle or pulse data output for Timer B

Location Range: 56578-56579 ($DD02-$DD03)


CIA #2 Data Direction Registers A and B

These Data Direction registers control the direction of data flow over
Data Ports A and B. For more details on the operation of these
registers, see the entry for the CIA #1 Data Direction Registers at
56322 ($DC02).

The default setting for Data Direction Register A is 63 (all bits


except 6 and 7 are outputs), and for Data Direction Register B the
default setting is 0 (all inputs). Bits 1 and 2 of Port B are changed
to output when the RS-232 device is opened.

56578 $DD02 C2DDRA


Data Direction Register A

Bit 0: Select Bit 0 of data Port A for input or output (0=input, 1=output)
Bit 1: Select Bit 1 of data Port A for input or output (0=input, 1=output)
Bit 2: Select Bit 2 of data Port A for input or output (0=input, 1=output)
Bit 3: Select Bit 3 of data Port A for input or output (0=input, 1=output)
Bit 4: Select Bit 4 of data Port A for input or output (0=input, 1=output)
Bit 5: Select Bit 5 of data Port A for input or output (0=input, 1=output)
Bit 6: Select Bit 6 of data Port A for input or output (0=input, 1=output)
Bit 7: Select Bit 7 of data Port A for input or output (0=input, 1=output)

56579 $DD03 C2DDRB


Data Direction Register B

Bit 0: Select Bit 0 of data Port B for input or output (0=input, 1=output)
Bit 1: Select Bit 1 of data Port B for input or output (0=input, 1=output)
Bit 2: Select Bit 2 of data Port B for input or output (0=input, 1=output)
Bit 3: Select Bit 3 of data Port B for input or output (0=input, 1=output)
www.unusedino.de/ec64/technical/project64/mapping_c64.html 95/126
25/9/2020 Mapping The C64
Bit 4: Select Bit 4 of data Port B for input or output (0=input, 1=output)
Bit 5: Select Bit 5 of data Port B for input or output (0=input, 1=output)
Bit 6: Select Bit 6 of data Port B for input or output (0=input, 1=output)
Bit 7: Select Bit 7 of data Port B for input or output (0=input, 1=output)

Location Range: 56580-56583 ($DD04-$DD07)


Timer A and B Low and High Bytes

These four timer registers are used to control Timers A and B. For
details on the operation of these timers, see the entry for Location
Range 56324-56327 ($DC04-$DC07).

The 64 Operating System uses the CIA #2 Timers A and B mostly for
timing RS-232 send and receive operations. Serial Bus timing uses CIA
#1 Timer B.

56580 $DD04 TI2ALO


Timer A (low byte)

56581 $DD05 TI2AHI


Timer A (high byte)

56582 $DD06 TI2BLO


Timer B (low byte)

56583 $DD07 TI2BHI


Timer B (high byte)

Location Range: 56584-56587 ($DD08-$DD0B)


Time of Day Clock

In addition to the two general purpose timers, the 6526 CIA chip has a
special purpose Time of Day Clock, which keeps time in a format that
humans can understand a little more easily than microseconds. For
more information about this clock, see the entry for Location Range
56328-56331 ($DC08-$DC0B). The 64's Operating system does not make
use of these registers.

56584 $DD08 TO2TEN


Time of Day Clock Tenths of Seconds

Bits 0-3: Time of Day tenths of second digit (BCD)


Bits 4-7: Unused

56585 $DD09 TO2SEC


Time of Day Clock Seconds

Bits 0-3: Second digit of Time of Day seconds (BCD)


Bits 4-6: First digit of Time of Day seconds (BCD)
Bit 7: Unused

56586 $DD0A TO2MIN


Time of Day Clock Minutes

Bits 0-3: Second digit of Time of Day minutes (BCD)


Bits 4-6: First digit of Time of Day minutes (BCD)
Bit 7: Unused

56587 $DD0B TO2HRS


Time of Day Clock Hours

Bits 0-3: Second digit of Time of Day hours (BCD)


Bit 4: First digit of Time of Day hours (BCD)
Bits 5-6: Unused
Bit 7: AM/PM flag (1=PM, 0=AM)

56588 $DD0C CI2SDR


Serial Data Port

The CIA chip has an on-chip serial port, which allows you to send or
receive a byte of data one bit at a time, with the most significant
bit (Bit 7) being transferred first. For more information about its
use, see the entry for location 56332 ($DC0C). The 64's Operating
System does not use this facility.

56589 $DD0D CI2ICR


Interrupt Control Register

Bit 0: Read / did Timer A count down to 0? (1=yes)


Write/ enable or disable Timer A interrupt (1=enable, 0=disable)
Bit 1: Read / did Timer B count down to 0? (1=yes)
Write/ enable or disable Timer B interrupt (1=enable, 0=disable)
Bit 2: Read / did Time of Day Clock reach the alarm time? (1=yes)
Write/ enable or disable TOD clock alarm interrupt (1=enable,
0=disable)
Bit 3: Read / did the serial shift register finish a byte? (1=yes)
Write/ enable or disable serial shift register interrupt (1=enable,
0=disable)
Bit 4: Read / was a signal sent on the FLAG line? (1=yes)
Write/ enable or disable FLAG line interrupt (1=enable, 0=disable)
Bit 5: Not used
Bit 6: Not used
Bit 7: Read / did any CIA #2 source cause an interrupt? (1=yes)
Write/ set or clear bits of this register (1=bits written with 1 will
be set, 0=bits written with 1 will be cleared)

This register is used to control the five interrupt sources on the


6526 CIA chip. For details on its operation, see the entry for 56333
www.unusedino.de/ec64/technical/project64/mapping_c64.html 96/126
25/9/2020 Mapping The C64
($DC0D). The main difference between these two chips pertaining to
this register is that on CIA #2, the FLAG line is connected to Pin B
of the User Port, and thus is available to the user who wishes to take
advantage of its ability to cause interrupts for handshaking purposes.

Location Range: 56590-$56591 ($DD0E-$DD0F)


See locations 56334 and 56334 for details

56590 $DD0E CI2CRA


Control Register A

Bit 0: Start Timer A (1=start, 0=stop)


Bit 1: Select Timer A output on Port B (1=Timer A output appears on
Bit 6 of Port B)
Bit 2: Port B output mode (1=toggle Bit 6, 0=pulse Bit 6 for one
cycle)
Bit 3: Timer A run mode (1=one-shot, 0=continuous)
Bit 4: Force latched value to be loaded to Timer A counter (1=force
load strobe)
Bit 5: Timer A input mode (1=count microprocessor cycles, 0=count
signals on CNT line at pin 4 of User Port)
Bit 6: Serial Port (56588, $DD0C) mode (1=output, 0=input)
Bit 7: Time of Day Clock frequency (1=50 Hz required on TOD pin,
0=60 Hz)

56591 $DD0F CI2CRB


Control Register B

Bit 0: Start Timer B (1=start, 0=stop)


Bit 1: Select Timer B output on Port B (1=Timer B output appears on
Bit 7 of Port B)
Bit 2: Port B output mode (1=toggle Bit 7, 0=pulse Bit 7 for one
cycle)
Bit 3: Timer B run mode (1=one shot, 0=continuous)
Bit 4: Force latched value to be loaded to Timer B counter (1=force
load strobe)
Bits 5-6: Timer B input mode
00 = Timer B counts microprocessor cycles
01 = Count signals on CNT line at pin 4 of User Port
10 = Count each time that Timer A counts down to 0
11 = Count Timer A 0's when CNT pulses are also present
Bit 7: Select Time of Day write (0=writing to TOD registers sets
alarm, 1=writing to ROD registers sets clock)

Location Range: 56592-56831 ($DD10-$DDFF)


CIA #2 Register Images

Since the CIA chip requires only enough addressing lines to handle 16
registers, none of the higher bits are decoded when addressing the
256-byte area that has been assigned to it. The result is that every
16-byte area in this 256-byte block is a mirror of every other. For
the sake of clarity in your programs, it is advisable not to use these
addresses.

Location Range: 56832-57087 ($DE00-$DEFF)


Reserved for I/O Expansion

This range of locations is not used directly by the 64's internal


hardware. It is, however, accessible via pin 7 of the Expansion Port.
It can be used to control cartridges which are connected to this port.
For example, the CP/M module uses this space to control which
microprocessor is in control of the system. The Z-80 microprocessor
is turned on and off by writing to 56832 ($DE00).

Another cartridge which uses this space is Simon's BASIC. This 16K
cartridge is addressed at memory locations 32768-49151 ($8000-$BFFF),
which means that it overlaps the regular BASIC ROM at 40960-49151
($A000-$BFFF). But since it contains additions to BASIC, it must use
the BASIC ROM as well. This problem is solved by copying the
cartridge at 32768-40959 ($8000-$9FFF) to RAM, and turning the
cartridge on and off by writing to or reading from location 56832
($DE00).

Location Range: 57088-57343 ($DF00-$DFFF)


CIA #2 Register Images

This range of locations is not used directly by the 64's internal


hardward, but is accessible via pin 10 of the Expansion Port. One
possible use for this I/O memory that Commodore has mentioned is an
inexpensive parallel disk drive (which presumable would be much faster
than the current serial model).

Alternate 53248-57343 ($D000-$DFFF)


Character Generator ROM

The character generator ROM supplies the data which is to form the
shapes of the text and graphics characters that are displayed on the
screen. Each character requires eight bytes of shape data, and these
eight-byte sequences are arranged in order in which the characters
appear in the screen code chart (see Appendix G). For example, the
first eight bytes of data in the ROM hold the shape information for
the commercial at sign (@), the next eight hold the shape of the
letter A, etc. In all, there are 4096 bytes, representing shape data
for two complete character sets of 256 characters each--1K each for
uppercase/graphics, reverse uppercase/reverse graphics, lowercase/
uppercase, and reverse lowercase/reverse uppercase.

The shape of each character is formed by an 8 by 8 matrix of screen


www.unusedino.de/ec64/technical/project64/mapping_c64.html 97/126
25/9/2020 Mapping The C64
dots. Whether any of the 64 dots is lit up or not is determined by
the bit patterns of the character data. Each byte of the Character
ROM holds a number from 0 to 255. This number can be represented by
eight binary digits of 0 or 1. The leftmost bit of these eight is
known as Bit 7, while the rightmost bit is called Bit 0. Each of
these binary digits has a bit value that is two times greater than the
last. The values of a bit set to 1 in each of the bit places are:

Bit 0 1 2 3 4 5 6 7
Value 1 2 4 8 16 32 64 128

A byte whose value is 255 has every bit set to 1


(128+64+32+16+8+4+2+1=255), while a byte whose value is 0 is made up
of all zero bits. Numbers in between are made up of combinations of
bits set to 1 and bits set to 0. If you think of every bit that holds
0 as a dot on the screen which is the color of the screen background,
and every bit that holds a 1 as a dot whose color is that of the
appropriate nybble in Color RAM, you can begin to get an idea of how
the byte values relate to the shape of the character. For example, if
you PEEK at the first eight bytes of the character ROM (the technique
is explained in the entry for location 1), you will see the numbers
60, 102, 110, 110, 96, 98, 60, 0. Breaking these data bytes down into
their bit values gives us a picture that looks like the following:

00111100 0 + 0 + 32 + 16 + 8 + 4 + 0 + 0 = 60
01100110 0 + 64 + 32 + 0 + 0 + 4 + 2 + 0 = 101
01101110 0 + 64 + 32 + 0 + 8 + 4 + 2 + 0 = 110
01101110 0 + 64 + 32 + 0 + 8 + 4 + 2 + 0 = 110
01100000 0 + 64 + 32 + 0 + 0 + 0 + 0 + 0 = 96
01100010 0 + 64 + 32 + 0 + 0 + 0 + 2 + 0 = 98
00111100 0 + 0 + 32 + 16 + 8 + 4 + 0 + 0 = 60
00000000 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 = 0

If you look closely, you will recognize the shape of the commercial at
sign (@) as it's displayed on your screen. The first byte of data is
60, and you can see that Bits 5, 4, 3, and 2 are set to 1. The chart
above shows that the bit values for these bits are 32, 16, 8, and 4.
Adding these together, you get 32+16+8+4=60. This should give you an
idea of how the byte value corresponds to the patterns of lit dots.
For an even more graphic display, type in the following program, which
shows the shape of any of the 512 characters in the ROM, along with
the number value of each byte of the shape.

10 DIM B%(7),T%(7):FOR I=0 TO 7:T%(I)=2^I:NEXT


20 POKE 53281,2:PRINT CHR$(147):POKE 53281,1:POKE 53280,0:POKE 646,11
30 POKE 214,20:PRINT:INPUT" CHARACTER NUMBER (0-511)";C$
40 C=VAL(C$):GOSUB 80:FOR I=0 TO 7
50 POKE 214,6+I:PRINT:PRINT TAB(23);B%(I);CHR$(20);" "
60 FOR J=7 TO 0 STEP-1:POKE 1319+(7-J)+I*40,32-128*((B%(I)ANDT%(J))=T%(J))
70 NEXT J,I:POKE 214,20:PRINT:PRINT TAB(27)" ":GOTO 30
80 POKE 56333,127:POKE 1,51:FOR I=0 TO 7
90 B%(I)=PEEK(53248+C*8+I):NEXT:POKE 1,55:POKE 56333,129:RETURN

If you have read about the VIC-II video chip, you know that it can
address only 16K of memory at a time, and that all display data such
as screen memory, character shape data, and sprite shape data must be
stored within that 16K block.

Since it would be very inconvenient for the VIC-II chip to be able to


access the character data only at the 16K block which includes
adresses 53248-57343 ($D000-$DFFF), the 64 uses an addressing trick
that makes the VIC-II chip see an image of the Character ROM at
4096-8191 ($1000-$1FFF) and at 36864-40959 ($9000-$9FFF). It is not
available in the other two blocks. To generate characters in these
blocks, you must supply your own user-defined character set, or copy
the ROM data to RAM. A machine language routine for doing this is
included in a sample program at the entry for 56576 ($DD00).

As indicated above, you are by no means limited to useing the


character data furnished by the ROM. The availability of user-defined
characters greatly extends the graphics power of the 64. It allows
you to create special text characters, like math or chemistry symbols
and foreign language alphabets. You can also develop special graphics
characters as a substitute for plotting points in bitmap graphics.
You can achieve the same resolution using a custom character as in
high-resolution bitmap mode, but with less memory. Once you have
defined the character, it is much faster to print it to the screen
than in would be to plot out all of the individual points.

To employ user-defined characters, you must first pick a spot to put


the shape data. This requires choosing a bank of 16K for video chip
memory (see the entry under Bits 0-1 of 56576 ($DD00) for the
considerations involved), and setting the pointer to the 2K area of
character memory in 53272 ($D018). It is then up to you to supply the
shape data for the characters. You can use part of the ROM character
set by reading the ROM and transferring the data to your character
shape area (see the entry for location 1 for a method of reading the
ROM).

Your original characters may be created by darkening squares on an 8


by 8 grid, converting all darkened squares to their bit values, and
then adding the bit values for each of the eight bytes. Or, you may
use one of the many character graphics editor programs that are
available commercially to generate the data interactively by drawing
on the screen.

One graphics mode, multicolor text mode, almost requires that you
define your own character set in order to use it effectively.
www.unusedino.de/ec64/technical/project64/mapping_c64.html 98/126
25/9/2020 Mapping The C64
Multicolor mode is enabled by Bit 4 of location 53270 ($D016).
Instead of using each bit to control whether an individual dot will be
foreground color (1) or background color (0), that mode breaks down
each byte of shape data in four bit-pairs. These bit pairs control
whether a dot will be the color in Background Color Register #0 (00),
the color in Background Color Register #1 (01), the color in
Background Color Register #2 (10), or the color in the appropriate
nybble of Color RAM (11). Since each pair of bits controls one dot,
each character is only four dots across. To make up for this, each
dot is twice as wide as a normal high-resolution dot.

::::::::::::::::
:: Chapter 7 ::
:: ::
::8K Operating::
:: System ::
:: Kernal ROM ::
::::::::::::::::

As with the section on the BASIC ROM, this section is not meant to be
a complete explanation of the Kernal ROM, but rather a guidepost for
further exploration. Where the exact instructions the Kernal ROM
routines use are important to your programming, it will be necessary
for you to obtain a disassembly listing of those routines and look at
the code itself.

Keep in mind that there is 8K of RAM underlying the Kernal ROM that
can be used by turning off interrupts and switching out the Kernal ROM
temporarily. Even without switching out the Kernal ROM, this RAM may
be read by the VIC-II chip if it is banked to use the top 16K of
memory, and may be used for graphics data. The Kernal and BASIC ROMs
may be copied to RAM, and the RAM versions modified to change existing
features or add new ones.

There are some differences between the version of the Kernal found on
the first few Commodore 64s and those found on the majority of newer
models. Those differences are discussed in the entries for the
sections on later Kernal additions (patches) at 58541-58623
($E4AD-$E4FF) an 65371-67407 ($FF5B-$FF7F).

The most obvious change causes the Color RAM at 55296 ($D800) to be
initialized to the background color when the screen is cleared on
newer models, instead of white as on the original models. Other
changes allow the new Kernal software to be used by either U.S. or
European 64s. Keep in mind that the Kernal is always subject to
change, and that the following discussion, while accurate at the time
written (mid-1983), may not pertain to later models. If future
changes are like past ones, however, they are likely to be minor ones.
The first place to look for these changes would be in the patch
sections identified above.

57344 $E000
Continuation of EXP Routine

This routine is split, with part on the BASIC ROM and the other part
here. Since the two ROMs do not occupy contiguous memory as on most
Commodore machines, the BASIC ROM ends with a JMP $E000 instruction.
Thus, while the BASIC interpreter on the 64 is for the most part the
same as on the VIC, the addresses for routines in this ROM are
displaced by three bytes from their location on the VIC.

57411 $E043 POLY1


Function Series Evaluation Subroutine 1

This routine is used to evaluate more comples expressions, and calls


the following routine to do the intermediate evaluation.

57433 $E059 POLY2


Function Series Evaluation Subroutine 2

This is the main series evaluation routine, which evaluates


expressions by using a table of the various values that must be
operated on in sequence to obtain the proper result.

57485 $E08D RMULC


Multiplicative Constant for RND

A five-byte floating point number which is multiplied by the seed


value as part of the process of obtaining the next value for RND>

57490 $E092 RADDC


Additive Constant for RND

The five-byte floating point number stored here is added to the seed
as part of the process of obtaining the value for RND.

57495 $E097 RND


Perform RND

This routine comes up with a random number in one of three ways,


depending on the argument X of RND(X). If the argument is positive,
the next RND value is obtained by multiplying the seed value in
location 139 ($8B) by one of the constants above, adding the other
constant, and scrambling the resulting bytes. This produces the next
number in a sequence. So many numbers can be produced in this way
before the sequence begins to repear that it can be considered random.

www.unusedino.de/ec64/technical/project64/mapping_c64.html 99/126
25/9/2020 Mapping The C64
If the argument is negative, the argument itself is scrambled, and
made the new seed. This allows creation of a sequence that can be
duplicated.

If the argument is 0, four bytes of the Floating Point Accumulator are


loaded from the low and high byte of Timer A, and the tenths of second
and second Time of Day Clock registers, all on CIA #1. This provides
a somewhat random value determined by the setting of those timers at
the moment that the command is executed, which becomes the new seed
value. The RND(1) command should then be used to generate further
random numbers.

The RND(0) implementation on the 64 has serious problems which make it


unusable for generating a series of random numbers when used by
itself. First of all, the Time of Day Clock on CIA #1 (see
56328-56331 ($DC08-$DC0B)) does not start running until you write to
the tenth of second register. The Operating System never starts this
clock, and therefore the two registers used as part of the floating
point RND(0) value always have a value of 0. Even if the clock was
started, however, these registers keep time in Binary Coded Decimal
(BCD) format, which means that they do not produce a full range of
numbers from 0 to 255. In addition, the Timer A high register output
ranges only from 0 to 66, which also imits the range of the final
floating point value so that certain numbers are never chosen.

57593 $E0F9
Call Kernal I/O Routines

This section is used when BASIC wants to call the Kernal I/O routines
CHROUT, CHRIN, CHKOUT, CHKIN, and GETIN. It handles any errors that
result from the call, and creates a 512-byte buffer space at the top
of BASIC and executes a CLR if the RS-232 device is opened.

57642 $E12A SYS


Perform SYS

Before executing the machine language subroutine (JSR) at the address


indicated, the .A, .X, .Y, and .P registers are loaded from the
storage area at 780-783 ($30C-$30F). After the return from subroutine
(RTS), the new values of those registers are stored back at 780-783
($30C-$30F).

57686 $E156 SAVE


Perform SAVE

This routine sets the range of addresses to be saved from the start of
BASIC program text and end of BASIC program text pointers at 43 ($2B)
and 45 ($2D), and calls the Kernal SAVE routine. This means that any
area of memory can be saved by altering these two pointers to point to
the starting and ending address of the desired area, and then changing
them back.

57701 $E165 VERIFY


Perform VERIFY

This routine sets the load/verify flag at 10 ($A), and falls through
to the LOAD routine.

57704 $E168 LOAD


Perform LOAD

This routine sets the load address to the start of BASIC (from pointer
at 43 ($2B)), and calls the Kerneal LOAD routine. If the load is
successful, it relinks the BASIC program so that the links agree with
the address to which it is loaded, and it resets the end of BASIC
pointer to reflect the new end of program text. If the LOAD was done
while a program was running, the pointers are reset so that the
program starts executing all over again from the beginning. A CLR is
not performed, so that the variables build so far are retained, and
their values are still accessible. The pointer to the variable area
is not changed, but if the new program is longer than the one that
loaded it, the variable table will be partially overwritten. This
will cause errors when the overwritten variables are referenced.
Likewise, strings whose text was referenced at its location within the
original program listing will be incorrect.

Since a LOAD from a program causes the program execution to continue


at the first line, when loading a machine language routine or data
file with a nonrelocating load (for example, LOAD"FILE",8,1) from a
program, you should read a flag and GOTO the line after the LOAD if
you don't want the program to keep rerunning indefinitely:

10 IF FLAG=1 THEN GOTO 30


20 FLAG=1:LOAD"FILE",8,1
30 REM PROGRAM CONTINUES HERE

57790 $E1BE OPEN


Perform OPEN

The BASIC OPEN statement calls the Kernal OPEN routine.

57799 $E1C7 CLOSE


Perform CLOSE

The BASIC CLOSE statement calls the Kernal CLOSE routine.

57812 $E1D4
Set Parameters for LOAD, VERIFY, and SAVE
www.unusedino.de/ec64/technical/project64/mapping_c64.html 100/126
25/9/2020 Mapping The C64

This routine is used in common by LOAD, SAVE, and VERIFY for setting
the filename, the logical file, device number, and secondary address,
all of which must be done prior to these operations.

57856 $E200
Skip Comma and Get Integer in .X

This subroutine is used to skip the comma between parameters and get
the following integer value in the .X register.

57862 $E206
Fetch Current Character and Check for End of Line

This subroutine gets the current character, and if it is 0 (end of


line), it pulls its own return address off the stack and returns.
This terminates both its own execution and that of the subroutine
which called it.

57870 $E20E
Check for Comma

This subroutine checks for a comma, moves the text pointer past it if
found, and returns an error if it is not found.

57881 $E219
Set Parameters for OPEN and CLOSE

This routine is used in common by OPEN and CLOSE for setting the
filename, the logical file, device number, and secondary address, all
of which must be done prior to these operations.

57956 $E264 COS


Perform COS

COS is executed by adding PI/2 to the contents of FAC1 and dropping


through to SIN.

57960 $E268 SIN


Perform SIN

This routine evaluates the SIN of the number in FAC1 (which represents
the angle in radians), and leaves the result there.

58036 $E2B4 TAN


Perform TAN

This routine evaluates the tangent of the number in FAC1 (which


represents the angle in radians) by dividing its sine by its cosine.

Location Range: 58080-58125 ($E2E0-$E30D)


Table of Constants for Evaluation of SIN, COS, and TAN

58080 $E2E0 PI2


The Five-Byte Floating Point Representation of the Constant PI/2

58085 $E2E5 TWOPI


The Five-Byte Floating Point Representation of the Constant 2*PI

58090 $E2EA FR4


The Five-Byte Floating Point Representation of the Constant 1/4

58095 $E2EF SINCON


Table of Constants for Evaluation of SIN, COS, and TAN

This table starts with a counter byte of 5, indicating that there are
six entries in the table. This is followed by the six floating point
constants of five bytes each.

58126 $E30E ATN


Perform ATN

The arc tangent of the number in FAC1 (which represents the angle in
radians) is evaluated using the 12-term series of operations from the
constant table which follows. The answer is left in FAC1.

58174 $E33E ATNCON


Table of Constants for ATN Evaluation

The table begins with a count byte of 11, which is followed by 12


constants in five-byte floating point representation.

58235 $E37B
Warm Start BASIC

This is the entry point into BASIC from the BRK routine at 65126
($FE66), which is executed when the STOP and RESTORE keys are both
pressed. It first executes the Kernal CLRCHN routine which closes all
files. It then sets the default devices, resets the stack and BASIC
program pointers, and jumps through the vector at 768 ($300) to the
next routine to print the READY prompt and enter the main BASIC loop.

58251 $E38B
Error Message Handler

This routine to print error messages is pointed to by the vector at


768 ($300). Using the .X register as an index, it either prints an
error message from the table at 41363 ($A193) or the READY prompt, and
www.unusedino.de/ec64/technical/project64/mapping_c64.html 101/126
25/9/2020 Mapping The C64
continues through the vector at 770 ($302) to the main BASIC loop.

58260 $E394
Cold Start BASIC

This initialization routine is executed at the time of power-up. The


RAM vectors to important BASIC routines are set up starting at 768
($300), the interpreter is initialized, the start-up messages are
printed, and the main loop entered through the end of the warm start
routine.

58274 $E3A2 INITAT


Text of the CHRGET Routine Which Runs at 115 ($73)

The text of the CHRGET routine is stored here, and moved to Page 0 by
the BASIC initialization routine. When creating a wedge in CHRGET, it
is possible to execute all or part of this code in place of the RAM
version.

59298 $E3BA
Initial RND Seed Value

At power-up time, this five-byte floating point constant is


transferred to 139 ($8B), where it functions as the starting RND seed
number. Thus, if RND is not initialized with a negative or zero
argument, it will always return the same sequence of numbers.

58303 $E3BF INIT


Initialize BASIC

This routine is called by the cold start routine to initialize all of


the BASIC zero-page locations which have a fixed value. This includes
copying the CHRGET routine from the ROM location above, to 115 ($73).

58402 $E422
Print BASIC Start-Up Messages

This routine prints the start-up message "**** COMMODORE 64 BASIC V2


****", calculates the amount of free memory, and prints the BYTES FREE
message.

58439 $E447
Table of Vectors to Important BASIC Routines

This table contains the vectors which point to the addresses of some
important BASIC routines. The contents of this table are moved to the
RAM table at 768 ($300).

58451 $E453
Copy BASIC Vectors to RAM

The cold start routine calls this subroutine to copy the table of
vectors to important BASIC routines to RAM, starting at location 768
($300).

58464 $E460 WORDS


Power-Up Messages

The ASCII text of the start-up messages "**** COMMODORE 64 BASIC V2


****" and "BYTES FREE" is stored here.

Location Range: 58551-58623 ($E4B7-E4FF)


Patches Added to Later Kernal Versions

This area contains code that was not found in the original version of
the Kernal. These additions were made to fix some bugs and to
increase Kernal compatibility between U.S. and European 64s.

58541 $E4AD
Patch for BASIC Call of CHKOUT

This patch was made to preserve the .A register if there was no error
returned from BASIC's call of the Kernal CHKOUT routine. Apparently,
the first version could cause a malfunction of the CMD and PRINT#
commands.

58551 $E4B7
35 Unused Bytes (all have the value of 170 ($AA)

Locaiton Range: 58586-65535 ($E4DA-$FFFF)


Kernal I/O Routines

After the conclusion of BASIC comes the part of this ROM which can be
considered the Kernal proper. This part contains all of the vectored
routines found in the jump table starting at 65409 ($FF81).

58586 $E4DA
Clear Color RAM to the Color in Background Color Register 0

This routine is a patch added to the more recent versions of the


Kernal. It is called by the routine which clears a screen line
(59903, $E9FF), and it places the color value in Background Color
Register 0 (53281, $D021) into the current byte of Color RAM pointed
to by USER (243, $F3).

In the original version of the Kernal, the routine that cleared a


screen line set the corresponding Color RAM to a value of 1, which
gives text characters a white foreground color. This was changed when
www.unusedino.de/ec64/technical/project64/mapping_c64.html 102/126
25/9/2020 Mapping The C64
the white color was found to sometimes cause light flashes during
screen scrolling. It was that white foreground color, however, that
enabled the user to POKE the screen code for a character into screen
RAM, and make that character appear on the screen in a color that
contrasted the blue background. This change to the Operating System
causes colors POKEd to screen RAM to be the same color as the
background, and thus they are invisible.

This is a fairly serious problem, because the technique of POKEing


characters to screen RAM has long been a staple of Commodore graphics
programming. Fortunately, the problem has an easy colution. Since
the Color RAM will be set to whatevere color is in Background Color
Register 0, what you have to do to initialize Color RAM to the color
you desire is change the background color to the desired foreground
color, clear the screen, and then change the background color back
again:

C=PEEK(53281):POKE 53281,HUE:PRINT CHR$(147):POKE 53281,C

58592 $E4E0
Pause after Finding a File on Cassette

This routine is a patch to the routine which finds a file on cassette.


After the file is found, the message FILETITLE FOUND appears on the
screen. On the original versions of the Kernal, the user would then
have to hit the Commodore key to continue the load. On the newer
versions, this patch causes a slight pause after the tape file is
round, during which time a keypress is looked for. If a key is
pressed, the loading process continues immediately. If it is not, the
load continues by itself after the end of the pause.

58604 $E4EC
Baud Rate Table for European (PAL) Standard Monitors

This table of prescaler values was added to later Kernal versions to


allow the same Kernal software to be used with either U.S. or European
64s. It contains the values which are required to obtain interrupts
at the proper frequency for the standard RS-232 baud rates, and
corresponds exactly in format to the table of values for the U.S.
(NTSC) monitor format at 65218 ($FEC2). Separate tables are required
because the prescaler values are derived from dividing the system
clock rate by the baud rate, and PAL machines operate with a slightly
slower clock frequency.

58624 $E500 IOBASE


Store Base Address of Memory-Mapped I/O Devices in .X and .Y Registers

This is one of the documented Kernal routines for which there is a


vector in the jump table at 65523 ($FFF3).

When called, this routine sets the .X register to the low byte of the
base address of the memory-mapped I/O devices, and puts the high byte
in the .Y register. This allows a user to set up a zero-page pointer
to the device, and to load and store indirectly through that pointer.
A program which uses this method, rather than directly accessing such
devices could be made to function without change on future Commodore
models, even though the I/O chips may be addressed at different
locations. This of course assumes that the CIA or a similar chip will
be used. This routine is of limited value for creating software that
is compatible with both the VIC-20 and the 64 because of the
differences in the VIA I/O chip that the VIC uses.

The current version of this routine loads the .X register with a 0,


and the .Y register with 220 ($DC), thus pointing to CIA #1, which is
at 56320 ($DC00).

58629 $E505 SCREEN


Store Number of Screen Rows and Columns in .Y and .X

This is a documented Kernal routine which is vectored in the jump


table at 65517 ($FFED), and is provided to allow for program
compatibility between computers.

When called, this subroutine returns the number of screen columns in


the .X register, and the number of screen rows in .Y. Thus, a program
can detect the screen format of the machine on which it is running,
and make sure that text output is formatted accordingly.

The present version of this routine loads the .X register with 40


($28) and the .Y register with 25 ($19).

58634 $E50A PLOT


Read/Set Location of the Cursor

The jump table entry for this documented Kernal is at 65520 ($FFF0).

The routine allows the user to read or set the position of the cursor.
If the carry flag is set with the SEC instruction before calling this
subroutine, cursor column (X position) will be returned in the .X
register, and the cursor row (Y position) will be returned in the .Y
register. If the carry flag is cleared with a CLC instruction before
entering this routine, and the .Y and .X registers are loaded with the
desired row and column positions respectively, this routine will set
the cursor position accordingly.

The current read routine loads .X and .Y from locations 214 ($D6) and
211 ($D3) respectively. The cursor set routine stores .X and .Y in
these locations, and calls the routine that sets the screen pointers
www.unusedino.de/ec64/technical/project64/mapping_c64.html 103/126
25/9/2020 Mapping The C64
at 58732 ($E56C).

The user can access this routine from BASIC by loading the .X, .Y, and
.P register values desired to the save area starting at 780 ($30C).

58648 $E518
Initialize Screen and Keyboard

This is the original CINT Kernal routine, to which additions were made
in later versions of the Kernal.

After calling the routine at 58784 ($E5A0) to set up default I/O


values, this routine initializes the cursor blink flags, the keyboard
decode vector, the key repeat delay and frequency counters, the
current color code, and maximum keyboard buffer size. It then falls
through to the next routine.

58692 $E544
Initialize the Screen Line Link Table and Clear the Screen

This routine initializes the screen line link table at 217 ($D9),
clears the screen, and clears the Color RAM to the background color.
It falls through to the next routine.

58726 $E566
Home the Cursor

This routine sets PNTR (211, $D3) and TBLX (214, $D6) to 0, and falls
through to the next routine.

58732 $E56C
Set Pointer to Current Screen Line

This routine sets the pointer PNT (209, $D1) to the address of the
first byte of the current logical line. In figuring this address, it
takes into account the status of the screen line link table, which can
indicate that two physical lines should be joined as one logical line.

58784 $E5A0
Set Default I/O Devices and Set Default Values for VIC-II Chip
Registers

This routine sets the keyboard and screen as the current input and
output devices. It then writes the default values found in the table
at 60601 ($ECB9) to the VIC-II chip.

58804 $E5B4 LP2


Get a Character from the Keyboard Buffer

This routine transfers the first character from the keybard buffer to
the .A register, bumps the rest of the characters one place up in
line, and decrements the pointer, showing how many characters are
waiting in the buffer.

58826 $E5CA
Wait for a Carriage Return from the Keyboard

This subroutine is called by the portion of the CHKIN routine that


handles keyboard input. It turns the cursor on, gets characters, and
echoes them to the screen until a carriage return has been entered.
It also looks for the shifted RUN/STOP key, and forces the output of
the commands LOAD and RUN if it finds it.

58930 $E632
Input a Character from Screen or Keyboard

This routine is the portion of the Kernal CHRIN routine that handles
input from the keyboard and screen devices. CHRIN gets one byte at a
time from the current screen position, or inputs a whole line from the
keyboard and returns it one byte at a time.

59012 $E684
Test for Quote Marks

This subroutine checks if the current character is a quotation mark,


and if it is, toggles the quote switch at 212 ($D4).

59025 $E691
Add a Character to the Screen

This is part of the routine that outputs a character to the screen.


It puts printable characters into screen memory.

59048 $E6A8
Return from Outputting a Character to the Screen

This is the common exit point for the screen portion of the CHROUT
routine.

59062 $E6B6
Advance the Cursor

This routine advances the cursor, and provides for such things as
scrolling at the end of the screen, and inserting a blank line in
order to add another physical line to the current logical line.

59137 $E701
Move Cursor Back over a 40-Column Line Boundary
www.unusedino.de/ec64/technical/project64/mapping_c64.html 104/126
25/9/2020 Mapping The C64

59158 $E716
Output to the Screen

This is the main entry point for the part of CHROUT that handles
output to the screen device. It takes an ASCII character number, and
tests if the character is printable. If it is, it prints it (taking
into consideration the reverse flag, if any inserts are left, etc.).
If it is a nonprinting character, the routine performs the appropriate
cursor movement, color change, screen clearing, or whatever else might
be indicated.

59516 $E87C
Move Cursor to Next Line

This subroutine moves the cursor down to the next line if possible, or
scrolls the screen if the cursor is on the last line.

59537 $E891
Output a Carriage Return

A carriage return is performed by clearing insert mode, reverse video,


and quote mode, and moving the cursor to the next line.

59553 $E8A1
If at the Beginning of a Screen Line, Move Cursor to Previous Line

59571 $E8B3
If at the End of a Screen Line, Move Cursor to the Next Line

59595 $E8CB
Check for a Color Change

This routine is used by the screen CHROUT routine to check if the


character to be printed is one that causes the current foreground
color to change (such as the CTRL-1 combination).

59601 $E8D1
PETASCII Color Code Equivalent Table

This table gives the PETASCII values of the color change characters
for each of the 16 possible colors. These values are:

144 ($90) Change to color 0 (black)


5 ($05) Change to color 0 (white)
28 ($1C) Change to color 0 (red)
159 ($9F) Change to color 0 (cyan)
156 ($9C) Change to color 0 (purple)
30 ($1E) Change to color 0 (green)
31 ($1F) Change to color 0 (blue)
158 ($9E) Change to color 0 (yellow)
129 ($81) Change to color 0 (orange)
149 ($95) Change to color 0 (brown)
150 ($96) Change to color 0 (light red)
151 ($97) Change to color 0 (dark gray)
152 ($98) Change to color 0 (medium gray)
153 ($99) Change to color 0 (light green)
154 ($9A) Change to color 0 (light blue)
155 ($9B) Change to color 0 (light gray)

59626 $E8EA
Scroll Screen

This subroutine moves all of the screen lines up, so that a blank line
is created at the bottom of the screen and the top screen line is
lost. If the top logical line is two physical lines long, all lines
are moved up two lines. Holding down the CTRL key will cause a brief
pause after the scroll.

59749 $E965
Insert a Blank Line on the Screen

This subroutine is used when INSERTing to add a blank physical line to


a logical line.

59848 $E9C8
Move Screen Line

This subroutine is used by the scroll routine to move one screen line
(and its associated Color RAM) up a line.

59872 $E9E0
Set Temporary Color Pointer for Scrolling

This subrouting sets up a pointer in 17-175 ($AE-$AF) to the Color RAM


address that corresponds to the temporary screen line address in
172-173 ($AC-$AD).

59888 $E9F0
Set Pointer to Screen Address of Start of Line

This subroutine puts the address of the first byte of the screen line
designated by the .X register into locations 209-210 ($D1-$D2).

59903 $E9FF
Clear Screen Line

This subroutine writes space characters to an entire line of screen


www.unusedino.de/ec64/technical/project64/mapping_c64.html 105/126
25/9/2020 Mapping The C64
memory, and clears the corresponding line of color memory to color in
Background Color Register 0 (53281, $D021).

59923 $EA13
Set Cursor Blink Timing and Color Memory Address for Print to Screen

This subroutine sets the cursor blink countdown and sets the pointer
to Color RAM. It then falls through to the next routine.

59932 $EA1C
Store to Screen

This routine stores the character in the .A register to the screen


address pointed to by 209 ($D1), and stores the color in the .X
register to the address pointed to by 243 ($F3).

59940 $EA24
Synchronize Color RAM Pointer to Screen Line Pointer

This subroutine sets the pointer at 243 ($F3) to the address of the
beginning of the line of Color RAM which corresponds to the current
line of screen RAM (whose pointer is at 209 ($D1)).

59953 $EA31
IRQ Interrupt Entry

This is the entry point to the standard IRQ interrupt handler. Timer
A of CIA #1 is set at power-on to cause an IRQ interrupt to occur
every 1/60 second. When the interrupt occurs, program flow is
transferred here via the CINV vector at 788 ($314). This routine
updates the software clock at 160-162 ($A0-$A2), handles the cursor
flash, and maintains the tape interlock which keeps the cassette motor
on if a button is pushed and the interlock flag is on. Finally, it
calls the keyboard scan routine, which checks the keyboard and puts
any character it finds into the keyboard buffer.

60039 $EA87 SCNKEY


Read the Keyboard

This subroutine is called by the IRQ interrupt handler above to read


the keyboard device which is connected to CIA #1 (see entry for 56320
($DC00) for details on how to read the keyboard).

It is the Kernal routine SCNKEY which can be entered from the jump
table at 65439 ($FF9F). This routine returns the keycode of the key
currently being pressed in 203 ($CB), sets the shift/control flag if
appropriate, and jumps through the vector at 655 ($28F) to the routine
that sets up the proper table to translate the keycode to PETASCII.
It concludes with the next routine, which places the PETASCII value of
the character in the keyboard buffer.

60128 $EAE0
Decode the Keystroke and Place its ASCII Value in the Keyboard Buffer

This is the continuation of the IRQ keyscan routine. It decodes the


keycode with the proper PETASCII table, and compares it with the last
keystroke. If if is the same, it checks to see if it is okay to
repeat the character without waiting for the key to be let up. If the
character should be printed, it is moved to the end of the keyboard
buffer at 631 ($277).

60232 $Eb48
Set Up the Proper Keyboard Decode Table

This routine is pointed to by the vector at 655 ($28F). Its function


is to read the shift/control flag at 653 ($28D), and set the value of
the decode table pointer at 245 ($F5) accordingly.

First it checks if the SHIFT/Commodore logo combination was pressed,


and if the toggle enable at 657 (291) will allow a change, the
character set will be changed to lowercase/uppercase or
uppercase/graphics by changing the VIC Memory Control Register at
53272 ($D018), and no character will be printed.

Next it sets the decode table pointer. There are 64 keys, and each
can have four different PETASCII values, depending on whether the key
is pressed by itself, or in combination with the SHIFT, CTRL, or
Commodore logo keys. Therefore, there are four tables of 64 entries
each to translate the keycode to PETASCII: the standard table, the
SHIFT table, the Commodore logo table, and the CONTROL table. The
routine will set up the pointer for the appropriate table, depending
on whether the SHIFT, CTRL, or logo key was pressed. The CTRL key
takes precedence, so that if another of these keys is pressed along
with the CTRL key, the CONTROL table is used.

60281 $EB79
Keyboard Decode Table Vectors

This table contains the two-byte addresses of the four keyboard decode
tables in low-byte, high-byte format.

60289 $EB81
Standard Keyboard Matrix Decode Table

This table contains the 64 PETASCII values for the standard keyboard,
one for each key which is struck by itself. The table is in keycode
order (see the keycode table in Appendix H for the correspondence of
keycode to key). A 65th byte with the value of 255 ($FF) marks the
www.unusedino.de/ec64/technical/project64/mapping_c64.html 106/126
25/9/2020 Mapping The C64
end of the table (this corresponds to a keypress value of 64, no key
pressed).

60354 $EBC2
SHIFTed Keyboard Matrix Decode Table

This table contains the 64 PETASCII values for the shifted keyboard,
one for each key which is struck while the SHIFT key is pressed. The
table is in keycode order (see the keycode table in Appendix H for the
correspondence of keycode to key). A 65th byte with the value of 255
($FF) marks the end of the table (this corresponds to a keypress value
of 64, no key pressed).

60419 $EC03
Commodore Logo Keyboard Matrix Decode Table

This table contains the 64 PETASCII values for the logo keyboard, one
for each key which is struck while the Commodore logo key is pressed.
The table is in keycode order (see the keycode table in Appendix H for
the correspondence of keycode to key). A 65th byte with the value of
255 ($FF) marks the end of the table (this corresponds to a keypress
value of 64, no key pressed).

60484 $EC44
Set Lowercase/Uppercase or Uppercase/Graphics Character Set

The part of the Kernal CHROUT routine that outputs to the screen uses
this subroutine to check for the special nonprinting characters that
switch the character set (CHR$(14) and CHR$(142)). If one of these is
the character to be printed, this routine makes the switch by setting
the location 53272 ($D018) accordingly.

60510 $EC5E
Set Flag to Enable or Disable Switching Character Sets

This subroutine is also used to check for special characters to print.


In this case, it checks for the characters that enable or disable the
SHIFT/logo combination from toggling the character set currently in
use (CHR$(8) and CHR$(9)). If one of these is to be printed, the flag
at 657 ($291) is changed.

60536 $EC78
Control Keyboard Matrix Decode Table

This table contains the 64 PETASCII values for the Control keyboard,
one for each key which is struck while the CTRL key is pressed. The
table is in keycode order (see the keycode table in Appendix H for the
correspondence of keycode to key). A 65th byte with the value of 255
($FF) marks the end of the table (this corresponds to a keypress value
of 64, no key pressed).

The only keys generally struck in combination with the CTRL key are
the ones that change the colors on the top row of the keyboard, but
this doesn't necessarily mean that the other CTRL key combinations
don't do anything. On the contrary, looking at the values in this
table, you can see that any of the first 32 values in the PETASCII
table can be produced by some combination of the CTRL key and another
key. CTRL-@ produces a CHR$(0). CTRL-A through CTRL-Z produce
CHR$(1) through CHR$(26). Ctrl-: is the same as CHR$(27), CTRL-Lira
(that's the slashed-L British pound sign) produces CHR$(28), CTRL-;
equals CHR$(29), CTRL-up arrow produces CHR$(30), and CTRL-= produces
CHR$(31).

Any of these combinations produce the same effect as the CHR$(X)


statement. For examble, CTRL-; moves the cursor over to the right,
CTRL-N switches to lowercase, CTRL-R turns on reverse video, and
CTRL-E changes the printing to white.

60601 $ECB9
Video Chip Register Default Table

This table contains the default values that are stored in the 47
VIC-II chip registers. It is interesting to note that this table
appears to be incomplete. While Sprite Color Registers 0-6 are
initialized to values of 1-7, Sprite Color Register 7 is initialized
to 76--the ASCII value of the letter L which begins on the next table.

60647 $ECE7
Text for Keyboard Buffer When SHIFT/RUN is Pressed

When the SHIFT and RUN keys are pressed, the ASCII text stored here is
forced into the keyboard buffer. That text is LOAD, carriage return,
RUN, carriage return.

60656 $ECF0
Low Byte Table of Screen Line Addresses

This table holds the low byte of the screen address for lines 0-24.
The high byte is derived from combining a value from the screen line
link table at 217 ($D9) with the pointer to screen memory at 648
($288).

60681 $ED09 TALK


Send TALK to a Device on the Serial Bus

This is a documented Kernal routine whose entry in the jump table is


65460 ($FFB4). When called, it ORs the device number in the
Accumulator with the TALK code (64, $40) and sends it on the serial
www.unusedino.de/ec64/technical/project64/mapping_c64.html 107/126
25/9/2020 Mapping The C64
bus. This commands the device to TALK.

60684 $ED0C LISTEN

This is a documented Kernal routine whose entry in the jump table is


65457 ($FFB1). When called, it ORs the device number in the
Accumulator with the LISTEN code (32, $20) and sends it on the serial
bus. This commands the device to LISTEN.

60689 $ED11
Send Command Code to a Device on the Serial Bus

This subroutine is used in common by many Kernal routines to send the


command code in the Accumulator to a device on the serial bus.

60736 $ED40
Send a Byte on the Serial Bus

This subroutine is used in common by several Kernal routines to send


the byte in the serial bus character buffer at 149 ($95) on the serial
bus.

60848 $EDB0
Time-Out Error on Serial Bus

This subroutine handles the case when the device does not respond by
setting the DEVICE NOT PRESENT error code and exiting.

60857 $EDB9 SECOND


Send a Secondary Address to a Device on the Serial Bus after LISTEN

This is a documented Kernal routine that can be entered from the jump
table at 65427 ($FF93). It sends a secondary address from the
Accumulator to the device on the serial bus that has just been
commanded to LISTEN. This is usually done to give the device more
particular instructions on how the I/O is to be carried out before
information is sent.

60871 $EDC7 TKSA


Send a Secondary Address to a Device on the Serial Bus after TALK

This is a documented Kernal routine that can be entered from the jump
table at 65430 ($FF96). It sends a secondary address from the
Accumulator to the device on the serial bus that has just been
commanded to TALK. This is usually done to give the device more
particular instructions on how the I/O is to be carried out before
information is sent.

60893 $EDDD CIOUT


Send a Byte to an I/O Device over the Serial Bus

This is a documented Kernal routine which can be entered from the jump
table at 65448 ($FFA8). Its purpose is to send a byte of data over
the serial bus. In order for the data to be received, the serial
device must have first been commanded to LISTEN and been given a
secondary address if necessary. This routine always buffers the
current character, and defers sending it until the next byte is
buffered. When the UNLISTEN command is sent, the last byte will be
sent with an End or Identify (EOI).

60911 $EDEF UNTLK


Send UNTALK to a Device on the Serial Bus

This is a documented Kernal routine whose entry in the jump table is


65451 ($FFAB). When called, it sends the UNTALK code (95, $5F) on the
serial bus. This commands any TALKer on the bus to stop sending data.

60926 $EDFE UNLSN


Send UNLISTED to a Device on the Serial Bus

This is a documented Kernal routine whose entry in the jump table is


65454 ($FFAE). It sends the UNLISTEN code (63, $3F) on the serial
bus. This commands any LISTENers to get off the serial bus, and frees
up the bus for other users.

60947 $EE13 ACPTR


Receive a Byte of Data from a Device on the Serial Bus

This is a documented Kernal routine whose entry point in the jump


table is 65445 ($FFA5). When called, it will get a byte of data from
the current TALKer on the serial bus and store it in the Accumulator.
In order to receive the data, the device must have previously been
sent a command to TALK and a secondary address if it needs one.

61061 $EE85
Set the Serial Clock Line Low (Active)

This subroutine clears the serial bus clock pulse output bit (Bit 4 of
CIA #2 Data Port A at 56576 ($DD00)).

61070 $EE8E
Set the Serial Clock Line High (Inactive)

This subroutine sets the serial bus clock pulse output bit to 1 (Bit 4
of CIA #2 Data Port A at 56576 ($DD00)).

61079 $EE97
Set Serial Bus Data Output Line Low
www.unusedino.de/ec64/technical/project64/mapping_c64.html 108/126
25/9/2020 Mapping The C64

This subroutine clears the serial bus data output to 0 (Bit 5 of CIA
#2 Data Port A at 56576 ($DD00)).

61097 $EEA9
Get Serial Bus Data Input Bit and Clock Pulse Input Bit

This subroutine reads the serial bus data input bit and clock pulse
input bit (Bits 7 and 6 of CIA #2 Data Port A at 56576 ($DD00)), and
returns the data bit in the Carry flag and the clock bit in the
Negative flag.

61107 $EEB3
Perform a One-Millisecond Delay

61115 $EEBB
Send Next RS-232 Bit (NMI)

This subroutine is called by the NMI interrupt handler routine to send


the next bit of data to the RS-232 device.

61230 $EF2E
Handle RS-232 Errors

This subroutine sets the appropriate error bits in the status register
at 663 ($297).

61258 $#F4A
Set the Word Length For the Current RS-232 Character

This routine takes the number of data bits to send per RS-232
character from the control register and puts it into the .X register
for use by the RS-232 routines.

61273 $EF59
Receive Next RS-232 Bit (NMI)

This routine is called by the NMI interrupt handler routine to receive


the next bit of data from the RS-232 device.

61310 $EF7E
Setup to Receive a New Byte from RS-232

61328 $EF90
Test If Start Bit Received from RS-232

61335 $EF97
Put a Byte of Received Data into RS-232 Receive Buffer

This routine checks for a Receive Buffer Overrun, stores the byte just
received in the RS-232 receive buffer, and checks for Parity Error,
Framing Error, or Break Detected Error. It then sets up to receive
the next byte.

61409 $EFE1
CHKOUT for the RS-232 device

The Kernal CHKOUT routine calls this subroutine to define the RS-232
device's logical file as an output channel. Before this can be done,
the logical file must first be OPENed.

61460 $F014
CHROUT for the RS-232 Device

The Kernal CHROUT routine calls this subroutine to output a character


to the RS-232 device. After the logical file has been OPENed and set
for output using CHKOUT, the CHROUT routine is used to actually send a
byte of data.

61517 $F04D
CHKIN for the RS-232 Device

The Kernal CHKIN routine calls this subroutine to define the RS-232
device's logical file as an input channel. A prerequisite for this is
that the logical file first be OPENed.

61574 $F086
GETIN for the RS-232 Device

The Kernal GETIN routine calls this subroutine to remove the next byte
of data from the RS-232 receive buffer and return it in the
Accumulator. The routine checks for the Receive Buffer Empty Error.
It is also called by the Kernal CHRIN routine, which essentially does
the same thing as GETIN for the RS-232 device.

61604 $F0A4
Stop CIA #2 RS-232 NMIs for Serial/Cassette Routines

This subroutine turns off the NMIs that drive the RS-232 routines
before any I/O is done using the serial bus or cassette device. Such
interrupts could throw off the timing of those I/O routines, and
interfere with the transmission of data.

61629 $F0BD
Kernal Control Messages

The ASCII text of the Kernal I/O control messages is stored here. The
last byte of every message has Bit 7 set to 1 (ASCII value + 128).
www.unusedino.de/ec64/technical/project64/mapping_c64.html 109/126
25/9/2020 Mapping The C64
The messages are:

I/O ERROR
SEARCHING
FOR
PRESS PLAY ON TAPE
PRESS RECORD & PLAY ON TAPE
LOADING
SAVING
VERIFYING
FOUND
OK

61739 $F12B
Print Kernal Error Message if in Direct Mode

This routine first checks location 157 ($9D) to see if the messages
are enabled. If they are, it prints the message indexed by the .Y
register.

61758 $F13E GETIN


Get One Byte from the Input Device

This is a documented Kernal routine whose jump table entry point is at


65508 ($FFE4). The routine jumps through a RAM vector at 810 ($32A).
Its function is to get a character from the current input device
(whose device number is stored at 153 ($99)). In practive, it
operates identically to the CHRIN routine below for all devices except
for the keyboard. If the keyboard is the current input device, this
routine gets one character from the keyboard buffer at 631 ($277). It
depends on the IRQ interrupt routine to rad the keyboard and put
characters into the buffer.

61783 $F157 CHRIN


Input a Character from the Current Device

This is a documented Kernal routine whose jump table entry point is at


65487 ($FFCF).

The routine jumps through a RAM vector at 804 ($324). Its function is
to get a character from the current input device (whose device number
is stored at 153 ($99)). This device must first have been OPENed and
then designated as the input channel by the CHKIN routine.

When this routine is called, the next byte of data available from this
device is returned in the Accumulator. The only exception is the
routine for the keyboard device (which is the default input device).
It the keyboard is the current input device, this routine blinks the
cursor, fetches characters from the keyboard buffer, and echoes them
to the screen until a carriage return is encountered. When a carriage
return is round, the routine sets a flag to indicate the length of the
last logical line before the return character, and reads the first
character of this logical line from the screen.

Subsequent calls to this routine will cause the next character in the
line to be read from the screen and returned in the Accumulator, until
the carriage return character is returned to indicate the end of the
line. Any call after this character is received will start the whole
process over again.

Note that only the last logical line before the carriage return is
used. Any time you type in more than 80 characters, a new logical
line is started. This routine will ignore any characters on the old
logical line, and process only the most recent 80-character group.

61898 $F1CA CHROUT


Output a Byte

This is a documented Kernal routine whose jump table entry point is at


65490 ($FFD2). The routine jumps through a RAM vector at 806 ($326).
It is probably one of the best known and most used Kernal routines,
because it sends the character in the Accumulator to the current
output device. Unless a device has been OPENed and designated as the
current output channel using the CHKOUT routine, the character is
printed to the screen, which is the default output device. If the
cassette is the current device, outputting a byte will only add it to
the buffer. No actual transmission of data will occur until the
192-byte buffer is full.

61966 $F20E CHKIN


Designate a Logical File As the Current Input Channel

This is a documented Kernal routine which can be entered from the jump
table at 65478 ($FFC6).

The routine jumps through a RAM vector at 798 ($31E). If you wish to
get data from any device other than the keyboard, this routine must be
called after OPENing the device, before you can get a data byte with
the CHRIN or GETIN routine. When called, the routine will designate
the logical file whose file number is in the .X register as the
current file, its device as the current device, and its secondary
address as the current secondary address. If the device on the
channel is a serial device, which requires a TALK command and
sometimes a secondary address, this routine will send them over the
serial bus.

62032 $F250 CHKOUT


Designate a Logical File As the Current Output Channel
www.unusedino.de/ec64/technical/project64/mapping_c64.html 110/126
25/9/2020 Mapping The C64

This is a documented Kernal routine which can be entered from the jump
table at 65481 ($FFC9).

The routine jumps through a RAM vector at 800 ($320). If you wish to
output data to any device other than the screen, this routine must be
called after OPENing the device, and before you output a data byte
with the CHROUT routine. When called, the routine will designate the
logical file whose file number is in the .X register as the current
file, its device as the current device, and its secondary address as
the current secondary address. If the device on the channel uses the
serial bus, and therefore requires a LISTEN command and possibly a
secondary address, this information will be sent on the bus.

62097 $F291 CLOSE


Close a Logical I/O File

CLOSE is a documented Kernal routine which can be entered via the jump
table at 65475 ($FFC3).

The routine jumps through a RAM vector at 796 ($31C). It is used to


close a logical file after all I/O operations involving that file have
been completed. This is accomplished by loading the Accumulator with
the logical file number of the file to be closed, and calling this
routine.

Closing an RS-232 file will de-allocate space at the top of memory for
the receiving and trasmit buffers. Closing a cassette file that was
opened for writing will force the last block to be written to
cassette, even if it is not a full 192 bytes. Closing a serial bus
device will send an UNLISTEN command on the bus. Remember, it is
necessary to properly CLOSE a cassette or disk data file in order to
retrieve the file later.

For all types of files, CLOSE removes the file's entry from the tables
of logical files, device, and secondary address at 601, 611, and 621
($259, $263, $26D), and moves all higher entries in the table down one
space.

62223 $F30F
Find the File in the Logical File Table

This subroutine is used by many Kernal routines to find the position


of the logical file in the logical file table at 601 ($259).

62239 $F31F
Set Current Logical File, Current Device, and Current Seconday Address

This subroutine is used to update the Kernal variables at 184-186


($B8-$BA) which holds the current logical file number, current device
number, and current secondary address number.

62255 $F32F CLALL


Close All Logical I/O Files

CLALL is a documented Kernal routine whose entry point in the jump


table is 65511 ($FFE7).

The routine jumps through a RAM vector at 812 ($32C). It closes all
open files, by resetting the index into open files at 152 ($98) to
zero. It then falls through to the next routine, which restores the
default I/O devices.

62259 $F333 CLRCHN


Restore Current Input and Output Devices to the Default Devices

This is a documented Kernal Routine which can be entered at location


65484 ($FFCC) in the jump table.

The routine jumps through a RAM vector at 802 ($322). It sets the
current input device to the keyboard, and the current output device to
the screen. Also, if the current input device was formerly a serial
device, the routine sends it an UNTALK command on the serial bus, and
if a serial device was formerly the current output device, the routine
sends it an UNLISTEN command.

62282 $F34A OPEN


Open a Logical I/O File

OPEN is a documented Kernal I/O routine. It can be entered from the


jump table at 65472 ($FFC0).

The routine jumps through a RAM vector at 794 ($31A). This routine
assigns a logical file to a device, so that it can be used for
Input/Output operations. In order to specify the logical file number,
the device number, and the secondary address if any, the SETLFS
routine must first be called. Likewise, in order to designate the
filename, the SETNAM routine must be used first. After these two
routines are called, OPEN is then called.

62622 $F49E LOAD


Load RAM from a Device

This is a documented Kernal routine, whose entry in the jump table


appears at 65493 ($FFD5).

The routine jumps through a RAM vector at 816 ($330). LOAD is used to
transfer data froma device directly to RAM. It can also be used to
www.unusedino.de/ec64/technical/project64/mapping_c64.html 111/126
25/9/2020 Mapping The C64
verify RAM, comparing its contents to those of a disk or tape file.
To choose between these operations you must set the Accumulator with a
0 for LOAD, or a 1 for VERIFY.

Since the LOAD routine performs an OPEN, it must be preceded by a call


to the SETLFS routine to specify the logical file number, device
number, and secondary address, and a call to the SETNAM routine to
specify the filename (a LOAD from tape can be performed without a
filename being specified). Then the .X and .Y registers should be set
with the starting address for the load, and the LOAD routine called.
If the secondary address specified was a 1, this starting address will
be ignored, and the header information will be used to supply the load
address. If the secondary address was a 0, the address supplied by
the call will be used. In either case, upon return from the
subroutine, the .X and .Y registers will contain the address of the
highest RAM location that was loaded.

62885 $F5A5
Print SEARCHING Message if in Direct Mode

62930 $F5D2
Print LOADING or VERIFYING

62941 $F5DD SAVE


Save RAM to a Device

This is a documented Kernal routine, whose entry in the jump table


appears at 65496 ($FFD8).

The routine jumps through a RAM vector at 818 ($332). SAVE is used to
transfer data directly from RAM to an I/O device. Since the SAVE
routine performs an OPEN, it must be preceded by a call to the SETLFS
routine to specify the logical file number, device number, and
secondary address, and a call to the SETNAM routine to specify the
filename (although a SAVE to the cassette can be performed without
giving a filename). A Page 0 pointer to the starting address of the
area to be saved should be set up, with the low byte of the address
first. The accumulator should be loaded with the Page 0 offset of
that pointer, then the .X and .Y registers should be set with the
ending address for the save, and the SAVE routine called.

63119 $F68F
If in Direct Mode, Print SAVING and Filename

63131 $F69B UDTIM


Update the Software Clock and Check for the STOP Key

UDTIM is a documented Kernal routine which can be entered through the


jump table at 65514 ($FFEA).

It is normally called by the IRQ interrupt handler once every sixtieth


of a second. It adds one to the value in the three-byte software
jiffy clock at 160-162 ($A0-$A2), and sets the clock back to zero when
it reaches the 24 hour point. In addition, it scans the keyboard row
in which the STOP key is located, and stores the current value of that
key in location 145 ($91). This variable is used by the STOP routine
which checks for the STOP key.

63197 $F6DD RDTIM


Read the Time From the Software Clock into the .A, .X, and .Y
Registers

This is a documented Kernal routine whose entry point in the jump


table is 65502 ($FFDE).

It reads the software clock (which counts sixtieths of a second) into


the internal registers. The .Y register contains the most significant
byte (from location 160 ($A0)), the .X register contains the middle
byte (from location 161 ($A1)), and the Accumulator contains the least
significant byte (from location 162 ($A2)).

63204 $F6E4 SETTIM


Set the Software Clock from the .A, .X, and .Y Registers

This documented Kernal routine can be entered from location 65499


($FFDB).

It performs the reverse operation from RDTIM, storing the value in the
.Y register into location 160 ($A0), the .X register into 161 ($A1),
and the Accumulator into 162 ($A2). Interrupts are first disabled, to
make sure that the clock will not be updated while being set.

63213 $F6ED STOP


Test STOP Key

STOP is a documented Kernal routine which can be entered from the jump
table at location 65505 ($FFE1).

It is vectored through RAM at 808 ($328). The routine checks to see


if the STOP key was pressed during the last UDTIM call. If it was,
the Zero flag is set to 1, the CLRCHN routine is called to set the
input and output devices back to the keyboard and screen, and the
keyboard queue is emptied.

63227 $F6FB
Set Kernal I/O Error Messages

This subroutine is used to handle I/O errors from Kernal I?O routines.
www.unusedino.de/ec64/technical/project64/mapping_c64.html 112/126
25/9/2020 Mapping The C64
It calls CLRCHN to restore default I/O devices. If Bit 6 of the flag
at 157 ($9D) is set, it prints I/O ERROR followed by the error number,
and then sets the Carry flag to indicate an error, with the error
number in the Accumulator. The Kernal error messages are not used by
BASIC, but may be used by machine language monitors and other
applications.

63276 $F72C
Get Next Tape File Header from Cassette

This routine reads in tape blocks until it finds a file header block.
It then prints out the FOUND message along with the first 16
characters of the filename.

63338 $F76A
Write Tape File Header Block

63440 $F7D0
Put Pointer to Tape Buffer in .X and .Y Registers

63447 $F7D7
Set I/O Area Start and End Pointers to Tape Buffer Start and End
Address

63466 $F7EA
Search Tape for a Filename

63511 $F817
Test Cassette Buttons and Handle Messages for Tape Read

This routine tests the sense switch, and if no buttons are depressed
it prints the PRESS PLAY ON TAPE message, and loops until a cassette
button is pressed, or until the STOP key is pressed. If a button is
pressed, it prints the message OK.

Since the message printing routine is entered after the test for
direct mode, these messages cannot be superseded by changing the flag
at 157 ($9D). You could have them harmlessly printed to ROM, however,
by changing the value of HIBASE at 648 ($288) temporarily to 160, and
then back to 4.

63534 $F82E
Check Cassette Switch

This subroutine is used to check if a button on the recorder has been


pressed.

63544 $F838
Test Cassette Buttons and Handle Messages for Tape Write

This routine tests the sense switch, and if no buttons are depressed
it prints the PRESS PLAY & RECORD message, and loops until a cassette
button is pressed, or until the STOP key is pressed. If a button is
pressed, it prints the message OK. These messages cannot be supressed
by changing the flag at 157 ($9D). See the entry for 63511 ($F817)
for more information.

63553 $F841
Start Reading a Block of Data from the Cassette

This subroutine tests the cassette switch and initializes various


flags for reading a block of data from cassette.

63588 $F864
Start Writing a Block of Data to the Cassette

This subroutine tests the cassette switch and initializes various


flags for writing a block of data to cassette.

63605 $F875
Common Code for Reading a Data Block from Tape and Writing a Block to Tape

This routine sets the actual reading or writing of a block of data.


It sets CIA #1 Timer B to call the IRQ which drives the actual reading
or writing routine, saves the old IRQ vector, and sets the new IRQ
vector to the read or write routine. It also blanks the screen so
that the video chip's memory addressing (which normally takes away
some of the 6510 microprocessor's addressing time) will not interfere
with the timing of the routines.

63696 $F8D0
Test the STOP Key during Cassette I/O Operations

This subroutine is used to test the STOP key during tape I/O
oeprations, and to stop I/O if it is pressed.

63714 $F8E2
Adjust CIA #1 Timer A for Tape Bit Timing

63788 $F92C
Read Tape Data (IRQ)

This is the IRQ handler routine that is used for reading data from the
cassette. At the end of the read, the IRQ vector is restored to the
normal IRQ routine.

64096 $FA60
Receive and Store the Next Character from Cassette
www.unusedino.de/ec64/technical/project64/mapping_c64.html 113/126
25/9/2020 Mapping The C64

This is the part of the cassette read IRQ routine that actually gets
the next byte of data from the cassette.

64398 $FB8E
Move the Tape SAVE/LOAD Address into the Pointer at 172

64407 $FB97
Reset Counters for Reading or Writing a New Byte of Cassette Data

64422 $FBA6
Toggle the Tape Data Output Line

This routine sets the CIA #1 Timer B, and toggles the Tape Data Output
line on the 6510 on-chip I/O port (Bit 3 of location 1).

64456 $FBC8
Write Data to Cassette--Part 2 (IRQ)

This IRQ handler routine is one part of the write data to cassette
routine

64618 $FC6A
Write Data fo Cassette--Part 1 (IRQ)

This IRQ handler routine is the other part of the write data to
cassette routine.

64659 $FC93
Restores the Default IRQ Routine

At the end of the tape I/O operations, this subroutine is used to turn
the screen back on and stop the cassette motor. It then resets the
CIA #1 Timer A to generate an interrupt every sixtieth of a second,
and restores the IRQ vector to point to the normal interrupt routine
that updates the software clock and scans the keyboard.

64696 $FCB8
Terminate Cassette I/O

This routine calls the subroutine above and returns from the
interrupt.

64714 $FCCA
Turn Off the Tape Motor

64721 $FCD1
Check the Tape Read/Write Pointer

This routine compares the current tape read/write address with the
ending read/write address.

64731 $FCDB
Advance the Tape Read/Write Pointer

This routine is used to move the pointer to the current read/write


address up a byte.

64738 $FCE2
Power-On Reset Routine

This is the RESET routine which is pointed to by the 6510 hardware


RESET vector at 65532 ($FFFC).

This routine is automatically executed when the computer is first


turned on. First, it sets the Interrupt disable flag, sets the stack
pointer, and clears the Decimal mode flag. Next, it tests for an
autostart cartridge. If one is found, the routine immediately jumps
through the cartridge cold start vector at 32768 ($8000). If no
cartridge is found, the Kernal initialization routines IOINIT, RAMTAS,
RESTOR, and CINT are called, the Interrupt disable flag is cleared,
and the BASIC program is entered through the cold start vector at
40960 ($A000).

64770 $FD02
Check for an Autostart Cartridge

This routine tests for an autostart cartridge by comparing the


characters at location 32772-6 ($8004-8) to the text below. The Zero
flag will be set if they match, and cleared if they don't.

64784 $FD10
Text for Autostart Cartridge Check

The characters stored here must be the fifth through the ninth
characters in the cartridge in order for it to be started on power-up.
These characters are the PETASCII values for CBM, each with the high
bit set (+128), and the characters "80".

64789 $FD15 RESTOR


Restore RAM Vectors for Default I/O Routines

This documented Kernal routine can be entered through the jump table
at 65418 ($FF8A).

It sets the values for the 16 RAM vectors to the interrupt and
important Kernal I/O routines in the table that starts at 788 ($314)
to the standard values held in the ROM table at 64816 ($FD30).
www.unusedino.de/ec64/technical/project64/mapping_c64.html 114/126
25/9/2020 Mapping The C64

64794 $FD1A VECTOR


Set the RAM Vector Table from the Table Pointed to by .X and .Y

This documented Kernal routine can be entered through the jump table
at 65421 ($FF8D).

It is used to read or change the values for the 16 RAM vectors to the
interrupt and important Kernal I/O routines in the table that starts
at 788 ($314). If the Carry flag is set when the routine is called,
the current value of the 16 vectors will be stored at a table whose
address is pointed to by the values in the .X and .Y registers. If
the Carry flag is cleared, the RAM vectors will be loaded from the
table whose address is pointed to by the .X and .Y registers. Since
this routine can change the vectors for the IRQ and NMI interrupts,
you might expect that the Interrupt disable flag would be set at its
beginning. Such is not the case, however, and therefore it would be
wise to execute an SEI before calling it and a CLI afterwards (as the
power-on RESET routine does) just to be safe.

64816 $FD30
Table of RAM Vectors to the Default I/O Routines

This table contains the 16 RAM I/O vectors that are moved to 788-819
($314-$333).

64848 $FD50 RAMTAS


Perform RAM Test and Set Pointers to the Top and Bottom of RAM

This documented Kernal routine, which can be entered through location


65415 ($FF87) of the jump table, performs a number of initialization
tasks.

First, it clears Pages 0, 2, and 3 of memory to zeros. Next, it sets


the tape buffer pointer to address 828 ($33C), and performs a
nondestructive test of RAM from 1024 ($400) up. When it reaches a
non-RAM address (presumably the BASIC ROM at 40960 ($A000)), that
address is placed in the top of memory pointer at 643-4 ($283-4). The
bottom of memory pointer at 641-2 ($281-2) is set to point to address
2048 ($800), which is the beginning of BASIC program text. Finally,
the pointer to screen memory at 648 ($288) is set to 4, which lets the
Operating System know that screen memory starts at 1024 ($400).

64923 $FD9B
Table of IRQ Vectors

This table holds the vectors to the four IRQ routines which the system
uses. The first points to Part 1 of the cassette write routine at
64618 ($FC6A), the second to Part 2 of the cassette write routine at
64461 ($FBCD), the third to the standard scan keyboard IRQ at 59953
($EA31), and the last to the cassette read routine at 63788 ($F92C).

64931 $FDA3 IOINIT


Initialize CIA I/O Devices

This documented Kernal routine, which can be entered through the jump
table at 65412 ($FF84), intializes the Complex Interface Adapter (CIA)
devices, and turns the volume of the SID chip off. As part of this
initialization, it sets CIA #1 Timer A to cause an IRQ interrupt every
sixtieth of a second.

65017 $FDF9 SETNAM


Set Filename Parameters

This is a documented Kernal routine, which can be entered through the


jump table at location 65469 ($FFBD).

It puts the value in the Accumulator into the location which stores
the number of characters in the filename, and sets the pointer to the
address of the ASCII text of the filename from the .X and .Y
registers. This sets up the filename for the OPEN, LOAD, or SAVE
routine.

65024 $FE00 SETLFS


Set Logical File Number, Device Number, and Secondary Address

This is a documented Kernal routine, which can be entered through the


jump table at location 65466 ($FFBA).

It stores the value in the Accumulator in the location which holds the
current logical file number, the value in the .X register is put in
the location that holds the current device number, and the value in
the .Y register is stored in the location that holds the current
secondary address. If no secondary address is used, the .Y register
should be set to 255 ($FF). It is necessary to set the values of the
current file number, device number, and secondary address before you
OPEN a file, or LOAD or SAVE.

65031 $FE07 READST


Read the I/O Status Word

This is a documented Kernal routine, which can be entered through the


jump table at location 65463 ($FFB7).

Whenever an I/O error occurs, a bit of the Status Word is set to


indicate what the problem was. The routine allows you to read the
status word (it is returned in the Accumulator). If the device was
the RS-232, its status register is read and cleared to zero. For the
www.unusedino.de/ec64/technical/project64/mapping_c64.html 115/126
25/9/2020 Mapping The C64
meanings of the various status codes, see the entry for location 144
($90) or 663 ($297) for the RS-232 device.

65048 $FE18 SETMSG


Set the Message Control Flag

This documented Kernal routine can be entered through its jump table
vector at 65424 ($FF90).

The routine controls the printing of error messages and control


messages by the Kernal. It Bit 6 is seto to 1 (bit value of 64),
Kernal control messages can be printed. These messages include
SEARCHING FOR, LOADING, and the like. If Bit 6 is cleared to 0, these
messages will not be printed (BASIC will clear this bit when a program
is running so that the messages do not appear when I/O is performed
from a program). Setting Bit 6 will not suppress the PRESS PLAY ON
TAPE or PRESS PLAY & RECORD messages, however.

If Bit 7 is set to 1 (bit value of 128), Kernal error messages can be


printed. If Bit 7 is set to 0, those error messages (for example, I/O
ERROR #nn) will be suppressed. Note that BASIC has its own set of
error messages (such as FILE NOT FOUND ERROR) which it uses in
preference to the Kernal's message.

65057 $E21 SETTMO


Set Time-Out Flag for IEEE Bus

This documented Kernal routine can be entered fromthe jump table at


65442 ($FFA2).

The routine sets the time-out flag for the IEEE bus. When timeouts
are enabled, the Commodore will wait for a device for 64 milliseconds,
and if it does not receive a response to its signal it will issue a
time-out error. Loading the Accumulator with a value less than 128
and calling this routine will enable time-outs, while using a value
over 128 will disable time-outs.

This routine is for use only with the Commodore IEEE add-on card,
which at the time of this writing was not yet available.

65061 $FE25 MEMTOP


Read/Set Top of RAM Pointer

This is a documented Kernal routine, which can be entered through the


jump table at location 65433 ($FF99).

It can be used to either read or set the top of RAM pointer. If


called with the Carry flag set, the address in the pointer will be
loaded into the .X and .Y registers. If called with the Carry flag
cleared, the pointer will be changed to the address found in the .X
and .Y registers.

65076 $FE34 MEMBOT


Read/Set Bottom of RAM Pointer

This is a documented Kernal routine, which can be entered through the


jump table at location 65436 ($FF9C).

It can be used to either read or set the bottom of RAM pointer. If


called with the Carry flag set, the address in the pointer willbe
loaded into the .X and .Y registers. If called with the Carry flag
cleared, the pointer will be changed to the address found in the .X
and .Y registers.

65091 $FE43
NMI Interrupt Entry Point

This routine is the NMI interrupt handler entry, which is pointed to


by the hardware NMI vector at 65530 ($FFFA).

Any time an NMI interrupt occurs, the Interrupt disable flag will be
set, and the routine will jump through the RAM vector at 792 ($318),
which ordinarily points to the continuation of this routine. The
standard handler first checks to see if the NMI was caused by the
RS-232 device. If not, the RESTORE key is assumed. The routine
checks for a cartridge, and if one is found it exits through the
cartridge warm start vector at 32770 ($8002). If not, the STOP key is
checked, and if it is being pressed, the BRK routine is executed. If
the RS-232 device was the cause of the NMI, the cartridge and STOP key
checks are bypassed, and the routine skips to the end, where it checks
whether it is time to send or receive a data bit via the RS-232
device.

65126 $FE66
BRK, Warm Start Routine

This routine is executed when the STOP/RESTORE combination of


keypresses occurs. In addition, it is the default target address of
the BRK instruction vector. This routine calls the Kernal
intialization routines RESTOR, IOINIT, and part of CINT. It then
exits through the BASIC warm start vector at 40962 ($A002).

65138 $FE72
NMI RS-232 Handler

This is the part of the NMI handler that checks if it is time to


receive or send a bit on the RS-232 channel, and takes the appropriate
action if it is indeed the time.
www.unusedino.de/ec64/technical/project64/mapping_c64.html 116/126
25/9/2020 Mapping The C64

65218 $FEC2
RS-232 Baud Rate Tables for U.S. Television Standard (NTSC)

This table contains the ten prescaler values for the ten standard baud
rates implemented by the RS-232 Control Register at 659 ($293). The
table starts with the two values needed for the lowest baud rate (50
baud) and finishes with the entries for the highest baud rate, 2400
baud. The RS-232 routines are handled by NMI interrupts which are
caused by the timers on CIA #2. Since the RS-232 device could both
receive and send a bit in a single cycle, the time between interrupts
should be a little less than half of the clock frequency divided by
the baud rate. The exact formula used is:

((CLOCK/BAUD)/2)-100

where CLOCK is the processor clock speed and BAUD is the baud rate.
The clock frequency for machines using the U.S. television standard
(NTSC) is 1,022,730 cycles per second, while the frequency for the
European (PAL) standard is 985,250 cycles per second. For this
reason, separate baud rate tables were added for European machines at
58604 ($E4EC).

65238 $FED6
RS-232 Receive the Next Bit (NMI)

The NMI handler calls this subroutine to input the next bit on the
RS-232 bus. It then calls the next subroutine to reload the timer
that causes the interrupts.

65306 $FF1A
Load the Timer with Prescaler Values from the Baud Rate Lookup Table

65352 $FF48
Main IRQ/BRK Interrupt Entry Point

The 6510 hardware IRQ/BRK vector at 65534 ($FFFE) points to this


address.

Anytime the BRK instruction is encountered or an IRQ interrupt occurs,


this routine will be executed. The routine first saves the .A, .X,
and .Y registers on the stack, and then tests the BRK bit of the
status register (.P) to see if a BRK was executed. If it was, the
routine exits through the RAM BRK vector at 790 ($316), where it will
usually be directed to the BRK routine at 65126 ($FE66). If not, the
routine exits through the RAM IRQ vector at 788 ($314), where it will
usually be directed to the handler that scans the keyboard at 59953
($EA31).

If you plan to change either of these vectors to your own routine,


remember to pull the stored register values off the stack before
finishing.

Location Range: 65371-65407 ($FF5B-$FF7F)


Patches Added to Later Kernal Versions

This area contains additional code not found in the original version
of the Kernal. It is used to test whether a European (PAL) or U.S.
(NTSC) standard monitor is used, and to compensate so that the
sixtieth of a second interrupt will be accurately timed on either
system.

65371 $FF5B CINT


Initialize Screen Editor and VIC-II Chip

This is a documented Kernal routine whose entry in the jump table is


located at 65409 ($FF81).

The start of the routine appears to be a patch that was added to later
versions of the Kernal. It first calls the old routine at 58648
($E518). This initializes the VIC-II chip to the default values, sets
the keyboard as the input device and the screen as the output device,
initializes the cursor flash variables, builds the screen line link
table, clears the screen, and homes the cursor. The new code then
checks the VIC Interrupt register to see if the conditions for a
Raster Compare IRQ have been fulfilled. Since the Raster Register was
initialized to 311, that can only occur when using a PAL system (NTSC
screens do not have that many scan lines). The PAL/NTSC register at
678 ($2A6) is set on the basis of the outcome of this test. The CIA
#1 Timer A is then set to cause an IRQ interrupt every sixtieth of a
second, using the prescaler figures for a PAL or NTSC system, as
appropriate.

65390 $FF6E
End of Routine to Set Timer for Sixtieth of a Second IRQ

This appears to be a patch added to compensate for the extra length of


the current version of this routine, which chooses either the PAL or
NTSC prescaler values for the timer.

65408 $FF80
Kernal Version Identifier Byte

This last byte before the jump table can be used to identify the
version of the Kernal. The first version has a 170 ($AA) stored here,
while the most current version at the time of this writing has a zero
in this location.

www.unusedino.de/ec64/technical/project64/mapping_c64.html 117/126
25/9/2020 Mapping The C64
The PET 64, a one-piece version with an integrated monochrome display,
has an identifier byte of 100 ($64). The Commodore 64 logo uses this
byte to recognize the PET 64, and adjust its display accordingly.

Location Range: 65409-65525 ($FF81-$FFF5)


Kernal Jump Table

The following jump table is provided by Commodore in an effort to


maintain stable entry points for key I/O routines. Each three-byte
table entry consists of a 6510 JMP instruction and the actual address
of the routine in the ROM. Although the actual address of the routine
may vary from machine to machine, or in later versions of the Kernal,
these addresses will stay where they are. By jumping to the entry
point provided by this table, rather than directly into the ROM, you
insure your programs against changes in the Operating System. In
addition, this jump table may help you write programs that will
function on more than one Commodore machine. The 15 table entries
from 65472-65514 ($FFC0-$FFEA) are the same for all Commodore
machines, from the earliest PET on.

As an additional aid, some of these routines are also vectored through


the table which starts at 788 ($314). Since this table is in RAM, you
can change those vectors to point to your own routines which support
additional I/O devices. Programs that use the jump table entry points
to the I/O routines will be able to use these I/O devices without a
problem.

The following table will give the entry point, routine name, RAM
vector if any, its current address, and a brief summary of its
function.

65409 ($FF81) CINT (65371, $FF5B) initialize screen editor and video chip
65412 ($FF84) IOINIT (64931, $FDA3) initialize I/O devices
65415 ($FF87) RAMTAS (64848, $FD50) initialize RAM, tape buffer, screen
65418 ($FF8A) RESTOR (64789, $FD15) restore default I/O vectors
65421 ($FF8D) VECTOR (64794, $FD1A) read/set I/O vector table
65424 ($FF90) SETMSG (65048, $FE18) set Kernal message control flag
65427 ($FF93) SECOND (60857, $EDB9) send secondary address after LISTEN
65430 ($FF96) TKSA (60871, $EDC7) send secondary address after TALK
65433 ($FF99) MEMTOP (65061, $FE25) read/set top of memory pointer
65436 ($FF9C) MEMBOT (65076, $FE34) read/set bottom of memory pointer
65439 ($FF9F) SCNKEY (60039, $EA87) scan the keyboard
65442 ($FFA2) SETTMO (65057, $FE21) set time-out flag for IEEE bus
65445 ($FFA5) ACPTR (60947, $FE13) input byte from serial bus
65448 ($FFA8) CIOUT (60893, $EDDD) output byte to serial bus
65451 ($FFAB) UNTLK (60911, $EDEF) command serial bus device to UNTALK
65454 ($FFAE) UNLSN (60926, $EDFE) command serial bus device to UNLISTEN
65457 ($FFB1) LISTEN (60684, $ED0C) command serial bus device to LISTEN
65460 ($FFB4) TALK (60681, $ED09) command serial bus device to TALK
65463 ($FFB7) READST (65031, $FE07) read I/O status word
65466 ($FFBA) SETLFS (65024, $FE00) set logical file parameters
65469 ($FFBD) SETNAM (65017, $FDF9) set filename parameters
65472 ($FFC0) OPEN (via 794 ($31A) to 62282, $F34A) open a logical file
65475 ($FFC3) CLOSE (via 796 ($31C) to 62097, $F291) close a logical file
65478 ($FFC6) CHKIN (via 798 ($31E) to 61966, $F20E) define an input channel
65481 ($FFC9) CHKOUT (via 800 ($320) to 62032, $F250) define an output channel
65484 ($FFCC) CLRCHN (via 802 ($322) to 62259, $F333) restore default devices
65487 ($FFCF) CHRIN (via 804 ($324) to 61783, $F157) input a character
65490 ($FFD2) CHROUT (via 806 ($326) to 61898, $F1CA) output a character
65493 ($FFD5) LOAD (via 816 ($330) to 62622, $F49E) load from device
65496 ($FFD8) SAVE (via 818 ($332) to 62941, $F5DD) save to a device
65499 ($FFDB) SETTIM (63204, $F6E4) set the software clock
65502 ($FFDE) RDTIM (63197, $F6DD) read the software clock
65505 ($FFE1) STOP (via 808 ($328) to 63213, $F6ED) check the STOP key
65508 ($FFE4) GETIN (via 810 ($32A) to 61758, $F13E) get a character
65511 ($FFE7) CLALL (via 812 ($32C) to 62255, $F32F) close all files
65514 ($FFEA) UDTIM (63131, $F69B) update the software clock
65517 ($FFED) SCREEN (58629, $E505) read number of screen rows and columns
65520 ($FFF0) PLOT (58634, $E50A) read/set position of cursor on screen
65523 ($FFF3) IOBASE (58624, $E500) read base address of I/O devices

Location Range: 65530-65535 ($FFFA-$FFFF)


6510 Hardware Vectors

The last six locations in memory are reserved by the 6510 processor
chip for three fixed vectors. These vectors let the chip know at what
address to start executing machine language program code when an NMI
interrupt occurs, when the computer is turned on, or when an IRQ
interrupt or BRK occurs.

65530 $FFFA
Non-Maskable Interrupt Hardware Vector

This vector points to the main NMI routine at 65091 ($FE43).

65532 $FFFC
System Reset (RES) Hardware Vector

This vector points to the power-on routine at 64738 ($FCE2).

65534 $FFFE
Maskable Interrupt Request and Break Hardware Vectors

This vector points to the main IRQ handler routine at 65352 ($FF48).

:::::::::::::::::::
:: Appendix A ::
www.unusedino.de/ec64/technical/project64/mapping_c64.html 118/126
25/9/2020 Mapping The C64
:: ::
:: A Beginner's ::
::Guide to Typing::
:: In Programs ::
:::::::::::::::::::

What Is a Program?

A computer cannot perform any task by itself. Like a car without gas,
a computer has potential, but without a program, it isn't going
anywhere. Most of the programs published in this book are written in
a computer language called BASIC. BASIC is easy to learn and is built
into all Commodore 64s.

BASIC Programs

Computers can be picky. Unlike the English language, which is full of


ambiguities, BASIC usually has only one right way of stating
something. Every letter, character, or number is significant. A
common mistake is substituting a letter such as O for the numeral 0, a
lowercase l for the numeral 1, or an uppercase B for the numeral 8.
Also, you must enter all punctuation such as colons and commas just as
they appears in the book. Spacing can be important. To be safe, type
in the listings exactly as they appear.

Braces and Special Characters

The exception to this typing rule is when you see the braces, such as
{DOWN}. Anything within a set of braces is a special character or
characters that cannot easily by listed on a printer. When you come
across such a special statement, refer to Appendix B, "How to Type In
Programs."

About DATA Statements

Some programs contain a section or sections of DATA statements. These


lines provide information needed by the program. Some DATA statements
contain actual programs (called machine language); others contain
graphics codes. These lines are especially sensitive to errors.

If a single number in any one DATA statement is mistyped, your machine


could lock up, or crash. The keyboard and STOP key may seem dead, and
the screen may go blank. Don't panic--no damage is done. To regain
control, you have to turn off your computer, then turn it back on.
This will erase whatever program was in memory, so always SAVE a copy
of your program before you RUN it. If your computer crashes, you can
LOAD the program and look for your mistake.

Sometimes a mistyped DATA statement will cause an error message when


the program is RUN. The error message may refer to the program line
that READs the data. The error is still in the DATA statements,
though.

Get to Know Your Machine

You should familiarize yourself with your computer before attempting


to type in a program. Learn the statements you use to store and
retrieve your programs from tape or disk. You'll want to save a copy
of your program, so that you won't have to type it in every time you
want to use it. Learn to use your machine's editing functions. How
do you change a line if you made a mistake? You can always retype the
line, but you at least need to know how to backspace. Do you know how
to enter reverse video, lowercase, and control characters? It's all
explained in your computer's manuals.

A Quick Review

1. Type in the program a line at a time, in order. Press RETURN at


the end of each line. Use backspace or the back arrow to correct
mistakes

2. Check the line you've typed against the line in the book. You can
check the entire program again if you get an error when you RUN the
program.

:::::::::::::::
::Appendix B ::
:: ::
::How to Type::
;:In Programs::
:::::::::::::::

To make it easy to know exactly what to type when entering one of


these programs into your computer, we have established the following
listing conventions.

Generally, Commodore 64 program listings will contain words within


braces which spell out any special characters: {DOWN} would mean to
press the cursor down key. {5 SPACES} would mean to press the space
bar five times.

To indicate that a key should be shifted (hold down the SHIFT key
while pressing the other key), the key would be unterlined in our
listings. For example, _S_ would mean to type the S key while holding
the SHIFT key. This would appear on your screen as a heart symbol.
If you find an underlined key enclosed in braces (e.g., {10 _N_}), you
should type the key as many times as indicated (in our example, you
www.unusedino.de/ec64/technical/project64/mapping_c64.html 119/126
25/9/2020 Mapping The C64
would enter ten shifted N's).

If a key is enclosed in special brackets, [<>], you should hold down


the Commodore key while pressing the key inside the special brackets.
(The Commodore key is the key in the lower-left corner of the
keyboard.) Again, if the key is preceded by a number, you should
press the key as many times as necessary.

Rarely, you'll see a solitary letter of the alphabet enclosed in


braces. These characters can be entered by holding down the CTRL key
while typing the letter in the braces. For example, {A} would
indicate that you should press CTRL-A.

About the quote mode: You know that you can move the cursor around
the screen with the CRSR keys. Sometimes a programmer will want to
move the cursor under program control. That's why you see all the
{LEFT}'s, {HOME}'s, and {BLU}'s in our programs. The only way the
computer can tell the difference between direct and programmed cursor
control is the quote mode.

Once you press the quote (the double quote, SHIFT-2), you are in the
quote mode. If you type something and then try to change it by moving
the cursor left, you'll only get a bunch of reverse-video lines.
These are the symbols for cursor left. The only editing key that
isn't programmable is the DEL key; you can still use DEL to back up
and edit the line. Once you type another quote, you are out of quote
mode.

You also go into quote mode when you INSerT spaces into a line. In
any case, the easiest way to get out of quote mode is to just press
RETURN. You'll then be out of quote mode and you can cursor up to the
mistyped line and fix it.

Use the following table when entering cursor and color control keys:

When You When You


Read: Press: Read: Press:
[CLR] SHIFT CLR/HOME [<1>] C= 1
[HOME] CLR/HOME [<2>] C= 2
[UP] SHIFT CRSR UP/DOWN [<3>] C= 3
[DOWN] CRSR UP/DOWN [<4>] C= 4
[LEFT] SHIFT CRSR LEFT/RIGHT [<5>] C= 5
[RIGHT] CRSR LEFT/RIGHT [<6>] C= 6
[RVS] CTRL 9 [<7>] C= 7
[OFF] CTRL 0 [<8>] C= 8
[BLK] CTRL 1 [F1] F1
[WHT] CTRL 2 [F2] SHIFT F1
[RED] CTRL 3 [F3] F3
[CYN] CTRL 4 [F4] SHIFT F3
[PUR] CTRL 5 [F5] F5
[GRN] CTRL 6 [F6] SHIFT F5
[BLU] CTRL 7 [F7] F7
[YEL] CTRL 8 [F8] SHIFT F8

::::::::::::::
::Appendix C::
:: ::
:: Screen ::
:: Location ::
:: Table ::
::::::::::::::

Row
0 1024 oooooooooooooooooooooooooooooooooooooooo
1064 oooooooooooooooooooooooooooooooooooooooo
1104 oooooooooooooooooooooooooooooooooooooooo
1144 oooooooooooooooooooooooooooooooooooooooo
1184 oooooooooooooooooooooooooooooooooooooooo
5 1224 oooooooooooooooooooooooooooooooooooooooo
1264 oooooooooooooooooooooooooooooooooooooooo
1304 oooooooooooooooooooooooooooooooooooooooo
1344 oooooooooooooooooooooooooooooooooooooooo
1384 oooooooooooooooooooooooooooooooooooooooo
10 1424 oooooooooooooooooooooooooooooooooooooooo
1464 oooooooooooooooooooooooooooooooooooooooo
1504 oooooooooooooooooooooooooooooooooooooooo
1544 oooooooooooooooooooooooooooooooooooooooo
1584 oooooooooooooooooooooooooooooooooooooooo
15 1624 oooooooooooooooooooooooooooooooooooooooo
1664 oooooooooooooooooooooooooooooooooooooooo
1704 oooooooooooooooooooooooooooooooooooooooo
1744 oooooooooooooooooooooooooooooooooooooooo
1784 oooooooooooooooooooooooooooooooooooooooo
20 1824 oooooooooooooooooooooooooooooooooooooooo
1864 oooooooooooooooooooooooooooooooooooooooo
1904 oooooooooooooooooooooooooooooooooooooooo
1944 oooooooooooooooooooooooooooooooooooooooo
24 1984 oooooooooooooooooooooooooooooooooooooooo
| | | | | | | | |
0 5 10 15 20 25 30 35 39

Column

::::::::::::::::
:: Appendix D ::
:: ::
www.unusedino.de/ec64/technical/project64/mapping_c64.html 120/126
25/9/2020 Mapping The C64
::Screen Color::
::Memory Table::
::::::::::::::::

Row
0 55296 oooooooooooooooooooooooooooooooooooooooo
55336 oooooooooooooooooooooooooooooooooooooooo
55376 oooooooooooooooooooooooooooooooooooooooo
55416 oooooooooooooooooooooooooooooooooooooooo
55456 oooooooooooooooooooooooooooooooooooooooo
5 55496 oooooooooooooooooooooooooooooooooooooooo
55536 oooooooooooooooooooooooooooooooooooooooo
55576 oooooooooooooooooooooooooooooooooooooooo
55616 oooooooooooooooooooooooooooooooooooooooo
55656 oooooooooooooooooooooooooooooooooooooooo
10 55696 oooooooooooooooooooooooooooooooooooooooo
55736 oooooooooooooooooooooooooooooooooooooooo
55776 oooooooooooooooooooooooooooooooooooooooo
55816 oooooooooooooooooooooooooooooooooooooooo
55856 oooooooooooooooooooooooooooooooooooooooo
15 55896 oooooooooooooooooooooooooooooooooooooooo
55936 oooooooooooooooooooooooooooooooooooooooo
55976 oooooooooooooooooooooooooooooooooooooooo
56016 oooooooooooooooooooooooooooooooooooooooo
56056 oooooooooooooooooooooooooooooooooooooooo
20 56096 oooooooooooooooooooooooooooooooooooooooo
56136 oooooooooooooooooooooooooooooooooooooooo
56176 oooooooooooooooooooooooooooooooooooooooo
56216 oooooooooooooooooooooooooooooooooooooooo
24 56256 oooooooooooooooooooooooooooooooooooooooo
| | | | | | | | |
0 5 10 15 20 25 30 35 39

Column

:::::::::::::::
::Appendix E ::
:: ::
:: Screen ::
::Color Codes::
:::::::::::::::

Value to POKE for Each Color

Low nybble High nybble Select multicolor


Color color value color value color value

Black 0 0 8
White 1 16 9
Red 2 32 10
Cyan 3 48 11
Purple 4 64 12
Green 5 80 13
Blue 6 96 14
Yellow 7 112 15
Orange 8 128 --
Brown 9 144 --
Light Red 10 160 --
Dark Gray 11 176 --
Medium Gray 12 192 --
Light Green 13 208 --
Light Blue 14 224 --
Light Gray 15 240 --

Where To POKE Color Values For Each Mode

Bit or
Mode * bit-pair Location Color value

Regular text 0 53281 Low nybble


1 Color memory Low nybble
Multicolor text 00 53281 Low nybble
01 53282 Low nybble
10 53283 Low nybble
11 Color memory Select Multicolor
Extended color 00 53281 Low nybble
text + 01 53282 Low nybble
10 53283 Low nybble
11 53284 Low nybble
Bitmapped 0 Screen memory Low nybble ++
1 Screen memory High nybble ++
Multicolor 00 53281 Low nybble
bitmapped 01 Screen memory High nybble ++
10 Screen memory Low nybble ++
11 Color memory Low nybble

* For all modes, the screen border color is controlled by POKEing


location 53280 with the low nybble color value.

+ In exteded color mode, Bits 6 and 7 of each byte of screen memory


serve as the bit-pair controlling background color. Because only Bits
0-5 are available for character selection, only characters with screen
codes 0-63 can be used in this mode.

++ In the bitmapped modes, the high and low nybble color values are
ORed together and POKEd into the same location in memory to control
the colors of the corresponding cell in the bitmap. For example, to
www.unusedino.de/ec64/technical/project64/mapping_c64.html 121/126
25/9/2020 Mapping The C64
control the colors of cell 0 of the bitmap, OR the high and low
nybbles and POKE the result into location 0 of screen memory.

:::::::::::::::
::Appendix F ::
:: ::
::ASCII Codes::
:::::::::::::::

[*** OMITTED ***]


[widely available elsewhere; not suitable for textual formatting]

::::::::::::::::
:: Appendix G ::
:: ::
::Screen Codes::
::::::::::::::::

[*** OMITTED ***]


[widely available elsewhere; not suitable for textual formatting]

:::::::::::::::
::Appendix H ::
:: ::
:: Commodore ::
::64 Keycodes::
:::::::::::::::

Key Keycode Key Keycode


A 10 6 19
B 28 7 24
C 20 8 27
D 18 9 32
E 14 0 35
F 21 + 40
G 26 - 43
H 29 LIRA 48
I 33 CLR/HOME 51
J 34 INST/DEL 0
K 37 LEFT ARROW 57
L 42 @ 46
M 36 * 49
N 39 ^ 54
O 38 : 45
P 41 ; 50
Q 62 = 53
R 17 RETURN 1
S 13 , 47
T 22 . 44
U 30 / 55
V 31 CRSR UP/DN 7
W 9 CRSR LF/RT 2
X 23 F1 4
Y 25 F3 5
Z 12 F5 6
1 56 F7 3
2 59 SPACE 60
3 8 RUN/STOP 63
4 11 NO KEY
5 16 PRESSED 64

The keycode is the number found at location 197 for the current key
being pressed. Try this one-line program:

10 PRINT PEEK(197):GOTO 10

::::::::::::::
:: Index ::
:: ::
::(by memory::
:: location)::
::::::::::::::

ABS 48216
AND 45033
ASC 46987
ATN 58126
BASIC
adding new commands 115,768
current line number 57
execution of statements 776,42980
expression evaluation 778, 44446, 44675
function evaluation 44967
pointer to bottom of string text 51
pointer to current data item address 65
pointer to current statement address 61
pointer to end of array storage 49
pointer to start of array storage 47
pointer to start of program text 43
pointer to start of variable storage 45
pointer to top of BASIC RAM 55
program text storage 2048
RAM vector table 768
Buffer
www.unusedino.de/ec64/technical/project64/mapping_c64.html 122/126
25/9/2020 Mapping The C64
cassette I/O buffer 178, 828
keyboard buffer 198, 631
RS-232 input buffer 247
RS-232 output buffer 249
text input buffer 512
cartridge, autostart ROM 32768
cassette
data output line 01
I/O buffer 828
Kernal ROM routines 63466-64737
motor control 01, 192
switch sense 01
character generator ROM 01, 4096, 36864, 53248
charcter graphics 53248
CHAREN 01
CHRGET 115, 58274
CHR$ 46828
CIA (Complex Interface Adapter)
CIA #1 56320-56335
CIA #2 56576-56591
data direction registers 56322, 56323, 56578, 56579
data ports 56320, 56321, 56576, 56577
timers 56334, 56335, 56590, 56591
clock
clock speed (6510 microprocessor) 56334
software clock 160
Time of Day clock 56328, 56584
CLOSE 57799
CLR 42590
CMD 43654
cold start, BASIC 40960, 58260
color
background 53281
border (frame) 53280
color codes 646
color RAM nybbles 55296
current character color 646
multicolor background registers 53282, 53283
PETASCII color change characters 59601
sprite color registers 53287-53294
sprite multicolor registers 53285, 53286
CONT 43095
COS 57956
DATA 43256
data direction register 00, 56322, 56323, 56578, 56579
data port 01, 56320, 56321, 56576, 56577
DEF 46003
DIM 45185
dynamic keyboard 198, 631
error
BASIC error handler 768, 42039, 58251
error message control flag 157
I/O error status 144
RS-232 I/O error status 663
EXP 49133
expression evaluation 778, 44446, 44675
floating point
addition 47207, 47210
division 47887, 47890
fixed-floating point conversion 05, 45969
floating-fixed point conversion 03, 45482, 45503
Floating Point Accumulators 97, 110
floating point-ASCII conversion 48605
multiplication 47656, 47667
subtraction 47194, 47194
FN 46068
FOR 42818
FRE 45949
garbage collection, string variable 46374
GET, GET# 43899
GOSUB 43139
GOTO 43168
graphics
bitmapped graphics 53265
character graphics 53248
extended background color mode 53265
fine scrolling 53265, 43271
multicolor mode 53271
raster position 53265, 53266
screen blanking 53265
sprites SEE sprite graphics
HIRAM 01
IF 43304
INT 48332
interrupt
CIA hardware FLAG line 56589, 56333
CIA serial shift register 56589, 56333
CIA Time of Day clock alarm 56589, 56333
CIA Timers A and B 56589, 56333
IRQ handler 59953, 65352
IRQ vector 788, 65534
light pen IRQ 53273, 53274
NMI handler 65091
NMI vector 792, 65530
raster compare IRQ 53266, 53273, 53274
sprite-display data collision IRQ 53273, 53275
sprite-sprite collision IRQ 53273, 53275
INPUT 43967
www.unusedino.de/ec64/technical/project64/mapping_c64.html 123/126
25/9/2020 Mapping The C64
INPUT# 43941
I/O
current device number 186
current filename address 187
current filename length 183
current input device 153
current I/O channel number 19
current logical file number 184
current output device 154
current secondary address 185
device number table 611
logical file table 601
number of I/O files open 152
RS-232 status 663
secondary address table 621
status word codes 144
joystick controllers 56320, 56321
Kernal
jump table 65409
RAM vector table 794
ACPTR 60947, 65445
CHKIN 798, 61966, 65478
CHKOUT 800, 62032, 65481
CHRIN 804, 61783, 65487
CHROUT 806, 61898, 65490
CINT 65371, 65409
CIOUT 60893, 65448
CLALL 812, 62255, 65511
CLOSE 796, 62097, 65475
CLRCHN 802, 62259, 65484
GETIN 810, 61758, 65508
IOBASE 58624, 65523
IOINIT 64931, 65412
LISTEN 60684, 65457
LOAD 816, 62622, 65493
MEMBOT 65076, 65436
MEMTOP 65061, 65433
OPEN 794, 62282, 65472
PLOT 58634, 65520
RAMTAS 64848, 65415
RDTIM 63197, 65502
READST 65031, 65463
RESTOR 64789, 65418
SAVE 818, 62941, 65496
SCNKEY 60039, 65439
SCREEN 58629, 65517
SECOND 60857, 65427
SETLFS 65024, 65466
SETMSG 65048, 65424
SETNAM 65017, 65469
SETTIM 63204, 65499
SETTMO 65057, 65442
STOP 808, 63213, 65505
TALK 60681, 65460
TKSA 60871, 65430
UDTIM 63131, 65514
UNLSN 60926, 65454
UNTLK 60911, 65451
VECTOR 64794, 65421
keyboard
current key pressed 203
keyboard buffer 631
keycodes 203
keyboard matrix 245, 655, 56321
last key pressed 197
number of characters in buffer 198
pointer to matrix lookup table 245
reading the keyboard 56320
repeating keys 650
LEFT$ 46848
LEN 46972
LET 43429
light pen 53267, 53268
LIST 42652
LOAD 57704
LORAM 01
MID$ 46903
NEW 42562
NEXT 44318
NMI 65095
ON GOSUB, ON GOTO 43339
OPEN 57790
Operating System (OS)
OS end of RAM pointer 643
OS screen memory pointer 648
OS start of RAM pointer 641
OR 45030
paddle controllers 54297, 54298
paddle fire button 56320, 56321
PAL/NTSC flag 678
PEEK 47117
POKE 47140
POS 45982
PRINT 43680
PRINT# 43648
program text area 43, 2048
program text input buffer 512
RAM
www.unusedino.de/ec64/technical/project64/mapping_c64.html 124/126
25/9/2020 Mapping The C64
BASIC pointer to end of RAM 55
RAM/ROM selection 01
OS pointer to end of RAM 643
OS pointer to start of RAM 641
random number generator 54299
READ 44038
registers, reading/setting from BASIC 780
REM 43323
RESER, power-on 64738, 65532
reset, VIC-II chip 53270
RESTORE 43037
RESTORE key, disabling 792, 808
RETURN 43218
RIGHT$ 46892
RND 139, 57495
RS-232
baud rate 659, 661, 665
baud rate tables 58604, 65218
buffers 247, 249
command register 660
connector pin assignments 56576, 56577
control register 659
duplex mode 660
handshaking protocol 660
Kernal ROM routines 57344-65535
parity 660
status register 663
stop bits 659
word length 659
RUN 43121
SAVE 57686
screen editor
current character color 646
cursor color RAM position 243
cursor flash 204, 205, 207
cursor maintenance 206, 647
cursor screen position 209, 211, 214
insert mode flag 216
key repeat 650, 651, 652
quote mode flag 212
reverse character flag 199
screen line link table 217
screen RAM 1024, 648, 53272
shift flag 653, 654
Serial Bus I/O 56576, 60681-61114
Serial Data Port (CIA) 56332, 56588
SGN 48185
SID chip register 54272-54300
SEE ALSO sound
SIN 57960
sound
ADSR envelope control 54278-54279, 54285-54286, 54292-54293
filtering 54293-54296
frequency (pitch) control 54272-54273, 54279-54280, 54286-54287
gate bit 54276
Oscillator 3 envelope generator 54300
Oscillator 3 output 54299
pulse waveform pulse width 54274-54275, 54281-54282, 54288-54289
ring modulation 54276, 54283, 54290
synchronization (hard sync) 54276, 54283, 54290
volume control 54296
waveform control 54276, 54283, 54290
sprite graphics
color registers 53287-53294
display priority 53275
enabling sprite display 53274
horizontal expansion 53277
multicolor color registers 53285-53286
multicolor sprites 53276
position registers 53248-53264
shape data pointers 2040
sprite-display data collision detection 53279
sprite-sprite collision detection 53278
vertical expansion 53271
SQR 49009
ST (I/O status word) 144
stack, 6510 microprocessor 256
STOP 43055
STOP key 145, 808
STR$ 46181
SYS 780, 57642
TAN 56083
Time of Day clock 56328-56331, 56584-56587
timers, hardware 56324-56327, 56334-56335, 56580-56583, 56590-56591
tokens, keyword 772, 774, 40972, 41042, 41088, 41118, 42364, 42772
User Port 56567-56577
USR 785
VAL 47021
variable
array variable storage 47
find or create variable routine 45195
storage format 45
string text area 51
VERIFY 57701
VIC-II CHIP
memory bank switching 56576
registers 53248-53294
SEE ALSO graphics, sprite graphics
www.unusedino.de/ec64/technical/project64/mapping_c64.html 125/126
25/9/2020 Mapping The C64
warm start, BASIC 40962, 58235
WAIT 47149
wedges 115

*********

End Project 64 etext Mapping The Commodore 64.

*********

www.unusedino.de/ec64/technical/project64/mapping_c64.html 126/126

También podría gustarte