"Finalmente, llegamos a las instrucciones que todos hemos estado esperando: ¡SEXO!"
/ del artículo sobre el microprocesador CDP1802 /

A principios de la década de 1970,
los juegos electrónicos simples como
Pong eran muy populares en los EE. UU. (En la URSS, sus
análogos aparecieron a la venta en 5-10 años). Como regla general, tales juegos no tenían un microprocesador y memoria en el sentido moderno de estas palabras, sino que se basaban en una lógica rígida. En consecuencia, los cartuchos reemplazables no tenían mucho sentido, y dónde estaban, eran solo un conjunto de puentes que incluían el juego deseado.
En 1977, se lanzaron dos consolas casi simultáneamente:
Fairchild Channel F y
RCA Studio II . Estas fueron las primeras consolas de juegos en forma de computadoras completas, con un microprocesador y programas de cartucho reemplazables. El RCA Studio II, que se discutirá, no solo es desarrollado por
RCA , sino por una persona específica:
Joseph A. Weisbecker (como toda la arquitectura COSMAC) .
El primer dispositivo de este tipo, el
Sistema 00 , también conocido como COSMAC FRED (1971), fue un prototipo y no fue producido en masa.
El procesador se implementó en la lógica habitual (en
FRED2 , en dos chips llamados CDP1801 R y U, que aparecieron en 1973). RAM estaba en la región de 256 bytes - 4 kb, además, FRED2 tenía una grabadora de cinta incorporada.
La primera implementación comercial de la arquitectura COSMAC fue el
COSMAC ELF . En 1976, ELF se posicionó como una computadora para jamones (se
publicó una serie de artículos en la revista Popular Electronics) y era una pequeña placa con interruptores de palanca, indicadores, un microprocesador CDP1802 (el mismo 1801, pero ya en un chip) y 256 bytes de RAM. Para él, había tarjetas de expansión adicionales que permitían mostrar gráficos en el monitor (usando el chip CDP1861), se conectaron un teclado externo y una grabadora de cinta. Basado en ELFs con extensiones, aparecieron ELF II y VIP. En las ROM COSMAC, había una máquina virtual llamada CHIP-8, mejorada para juegos primitivos (comandos para generar y mover sprites de software, generar números aleatorios, etc.) Había otras computadoras y terminales primitivas basadas en esta arquitectura.
Todos estos dispositivos fueron predecesores directos de RCA Studio II y tienen una arquitectura de hardware y software extremadamente cercana.
RCA Studio II fue lanzado en 1977 y luego tenía un precio de $ 150 ($ 600 por dinero actual). Como suele suceder, el primero en el mercado no es necesariamente el más exitoso. En 2008, la revista PC World
reconoció esta consola como la peor consola de juegos de todos los tiempos (que, en principio, no está lejos de la verdad). Una imagen en blanco y negro de cuadrados, la ausencia de joysticks (en lugar de dos campos de 10 botones) y una docena de juegos, por decirlo suavemente, no Compradores satisfechos.
Además, todos los juegos (tanto integrados como vendidos en cartuchos) se escribieron en el pseudocódigo de la máquina virtual ST2 (la misma idea que con CHIP-8 en COSMAC), lo que lo hizo muy lento.
RCA logró lanzar aproximadamente 64 mil unidades de RCA Studio II, sin contar los clones que aparecieron más tarde (Toshiba Visicom, Conic M-1200, etc.) Con el advenimiento de
Atari VCS , el anticuado RCA Studio II y Fairchild Channel F abandonaron instantáneamente la pelea.
CPU
Como fabricante de chips, RCA eligió su propio producto como procesador de decodificador: el
microprocesador RCA CDP1802 , que opera a 1.78 MHz y fabricado con tecnología CMOS.
Su predecesor fue el CDP1801, un procesador de dos chips (totalmente compatible con 1802):
CDP1802 es conocido por su versión resistente a la radiación (silicio sobre zafiro), en el que se utilizó, por ejemplo, en la estación interplanetaria de
Galileo , volando a Júpiter en la década de 1990 (había 6 procesadores de este tipo), así como en
MAGSAT .
El procesador tiene un esquema de uso de registro bastante complicado. Tiene un acumulador D de 8 bits y dieciséis registros de 16 bits - R0..RF (R0-R15), cada uno de los cuales puede convertirse en un puntero de instrucción, dependiendo del contenido del registro P de 4 bits (apuntando a uno de R), modificable SEP Rn equipo. En otras palabras, ¡no hay una sola PC en el procesador!
Además, cualquiera de R0 ... R15 puede convertirse en índice (dirección). La selección se determina en función del valor en el registro X de 4 bits (modificado por el comando SEX Rn), después de lo cual el R seleccionado se considera indexado para algunos comandos.
El registro de dirección para DMA es siempre R0. Dentro de la interrupción, el contador de instrucciones es R1.
Hay un registro T de 8 bits, que se usa para guardar automáticamente los registros X y P cuando ocurre una interrupción. Las interrupciones se habilitan configurando el indicador de activación de interrupción de IE mediante los comandos RET o DIS.
Los registros de 4 bits I y N contienen la instrucción actual ejecutada por el procesador.
Hay un registro de bandera - DF. Más precisamente, una bandera, ya que es de un solo dígito y contiene solo una bandera de acarreo.
Además, el procesador tiene un puerto de salida Q de un solo bit, cuyo estado es cambiado por los comandos SEQ y REQ.
Como en muchos procesadores de esa generación, la pila en el sentido habitual está ausente aquí (no hay comandos PUSH, POP ni el puntero de la pila) y, si es necesario, se implementa mediante las instrucciones existentes.
Tampoco hay instrucciones tradicionales para llamar a las rutinas. La transición a la subrutina se lleva a cabo utilizando la instrucción SEP Rn que, recuerdo, hace que el Rn indicado sea un contador de comandos. Para regresar, se usa la misma instrucción SEP, pero con un registro que era el contador de comandos antes de la llamada. O (en una versión más universal, pero más lenta) se utilizan MARK y RET.
Además de los saltos condicionales e incondicionales tradicionales (por cierto, todos son absolutos), hay varias instrucciones SKIP que, cuando se cumple la condición, omiten la siguiente instrucción SKIP (dos bytes). SKIP incondicional también se proporciona.
El procesador 1802 a menudo se conoce como uno de los primeros procesadores RISC. Sin embargo, en el mismo contexto, se hace mención de, digamos, 6502, así como algunos otros. Es cierto que la arquitectura no es del todo ordinaria y, desde el punto de vista de la programación, provoca sentimientos encontrados. Por un lado, hay hasta dieciséis registros de 16 bits. Por otro lado, sus contenidos directamente solo se pueden reducir y aumentar en uno. Por ejemplo, poner una constante en Rn se ve así:
ldi $01 ; const -> D plo r6 ; D -> R6.0 ldi $02 ; const -> D phi r6 ; D -> R6.1
Por lo tanto, la mayor parte del código está moviendo bytes de un lado a otro.
De las transiciones por condición, de hecho, solo hay una transición a cero (solo se considera la situación cuando 0 está en el acumulador D) y la bandera de transferencia. Los bucles típicos son los siguientes:
loop: ... dec r7 ; R7-- glo r7 ; R7 -> D bnz loop loop: ... adi 2 ; D = D + const xri $07 ; compare using XOR. (D == const) -> D bnz loop
Todas las instrucciones aritméticas y lógicas funcionan solo con la batería D.
Además del puerto de un solo bit controlado por SEQ / REQ, también hay un puerto de cuatro bits controlado por los comandos OUT / INP. Desafortunadamente, no se usa en RCA Studio II.
MEMORIA
Hay: 2 KB de ROM (BIOS + cinco juegos integrados) 512 bytes de RAM (la mitad está reservada para video)
Tarjeta de memoria
000-2FF ROM RCA System ROM : SP2 300-3FF ROM RCA System ROM : BIOS 400-7FF ROM ( ) 400-7FF ROM ( ) 1024 800-8FF RAM (256 ) 900-9FF RAM (256 ) A00-BFF ROM ( ) C00-DFF --- , 800-9FF E00-FFF ROM ( )
Es necesario tener en cuenta específicamente que para los juegos y programas en cartuchos solo está disponible una parte del BIOS: el que contiene SP2 (innecesario, en general), las imágenes de números del 0 al 9 y el controlador de interrupción estándar para video.
VIDEO
Para los gráficos, se utiliza el chip
RCA CDP1861 , el llamado "Pixie".
El RCA Studio II estándar tiene una salida estándar con solo antena (RF), sin embargo, las personas lo
remodelan en un compuesto para que la calidad sea mejor (casi escribí "para una mejor reproducción del color" :))
Técnicamente, el controlador de video proporciona una resolución máxima de 64x128 en dos colores (blanco y negro). Sin embargo, esto requiere 1024 bytes de memoria de video, y en Studio II la cantidad total de RAM es de 512 bytes. Por lo tanto, la resolución es 64x32 (que requiere 256 bytes). La resolución horizontal (64) es fija. En una línea de 64 píxeles, siempre se muestran 8 bytes, y esto ocurre durante 14 ciclos de procesador.
El controlador de interrupción del BIOS se usa para mostrar la memoria ($ 900- $ 9ff) en la pantalla. La interrupción es iniciada por el controlador de video y ocurre 60 veces por segundo (NTSC) .El procesador de BIOS realiza todas las operaciones necesarias: el programa ejecutable solo necesita cambiar la memoria de video, en la que cada bit corresponde directamente a un punto negro o blanco (de izquierda a derecha, de arriba a abajo).
Sin embargo, nada le impide escribir su propio controlador. El caso más simple es la resolución de 64x128, ya que es natural para un controlador de video. Para él, en el controlador es suficiente escribir la dirección de la memoria de video en R0 (de dónde vendrán los datos para la pantalla) y los bytes comenzarán a mostrarse a través del DMA, llenando el marco. La situación es más complicada con resoluciones verticales distintas de 128. Allí debe ingresar demoras y duplicar datos cambiando R0 (consulte la descripción de cdp1861 y la fuente del BIOS).
En principio, incluso puede hacer una resolución vertical variable, no enviar nada a una parte de la pantalla y también especificar ROM, no RAM (o parcialmente ROM y parcialmente RAM) como memoria de video. También puede implementar el desplazamiento vertical, cambiando la inicial en R0 La dirección desde la cual los datos comienzan a emitirse al controlador.
Tenga en cuenta que en la salida INT del controlador de video, la unidad aparece dos líneas antes de que el haz alcance la región visible. Por lo tanto, el controlador de interrupciones generalmente comienza con un retraso que le permite comenzar a mostrar la memoria a tiempo.
El controlador de video también tiene una salida EFX, en la cual 0 aparece para 4 líneas antes de que el haz aparezca en la región visible y luego para las últimas 4 líneas de esta área. La salida EFX está conectada al procesador EF1 y su estado se puede verificar con el comando B1 (BN1).
La expectativa típica de un haz de retorno a lo largo del marco se implementa de la siguiente manera:
... delay: bn1 delay ; wait for EFX in video chip ...
Como se señaló anteriormente, en la ROM no hay imágenes de letras y signos. Sin embargo, todavía hay números (después de todo, en los juegos integrados necesitas mostrar de alguna manera los puntos y el número de jugador). Sin embargo, incluso aquí lograron ahorrar:
Como puede ver, los números están unidos para que los restantes se obtengan de varios adyacentes.
Sonido
Digamos que hay sonido. Pero no mas. NE555 está conectado al puerto de salida de un solo bit del CDP1802 con una correa y luego está todo conectado al altavoz incorporado en el decodificador. Cuando se suministra una unidad a la entrada RST NE555 (por el comando del procesador SEQ), comienza a emitir un pitido a una frecuencia de 625Hz. Cuando cero (por el comando REQ) - el pitido se detiene. En realidad eso es todo. Sin embargo, todavía hay un condensador debido al cual, al comienzo del chirrido, la frecuencia disminuye gradualmente a la mitad en el transcurso de 0,4 segundos (es decir, se obtiene un chirrido adicional).

En el controlador estándar de interrupción del BIOS, además de la parte responsable del video, hay una pieza que verifica el contenido de una celda de memoria específica y, si no hay cero, enciende el chirrido y comienza a disminuir cíclicamente el contenido de la celda $ 08CD (cuando se alcanza el cero, el chirrido se apaga). Por lo tanto, no puede molestarse con la autograbación en el puerto, simplemente configure la duración del chirrido y se producirá en segundo plano, sin detener el programa:
ldi $8cd & $ff plo rf ldi 250 ; str rf ...
Lo mismo también se puede hacer manualmente (después de apagar las interrupciones):
; sex r3 ; set X to R3 dis ; return X to R5, P to R3, 0-IE, R3=R3+1 db 53h ; forces X=5 P=3 - which is no change ; seq ; ldi 250 ; delay plo r6 delay: dec r6 glo r6 bnz delay ; req ; sex r3 ; set X to R3 ret ; return X to R5, P to R3, 1-IE, R3=R3+1 db 53h ; forces X=5 P=3 - which is no change
PROGRAMAS
En la década de 1970, se escribieron un poco más de una docena de juegos y varios otros programas (principalmente por RCA). Casi todos ellos fueron escritos no en ensamblador, sino en
pseudocódigo - en la ROM STB hay una máquina virtual de intérprete especial ST2. Es difícil decir exactamente qué motivó tal decisión. Lo más probable es que la idea fuera ahorrar memoria: los juegos realmente tienen un volumen significativamente menor. En general, las orejas ST2 crecen a partir de una VM similar llamada
CHIP-8 , utilizada en COSMAC. Aunque las dos máquinas virtuales no son compatibles entre sí, ya en la década de 2000 se escribió el intérprete CHIP-8 para RCA Studio II. Dada la extrema similitud de las arquitecturas, no es sorprendente que, como escribe el intérprete, los juegos con COSMAC que no requerían mucha memoria comenzaran sin problemas en RCA Studio II.
Por desgracia, las máquinas virtuales en una arquitectura de este tipo funcionan muy lentamente, lo que deja una huella indeleble en los propios juegos. Más tarde, en 2013, Paul Robson escribió alrededor de una docena de juegos más, ya en ensamblador y los
distribuyó con la fuente.
DESARROLLO
Inicialmente, según los testigos, el desarrollo de RCA Studio II se realizó incluso sin ensamblador, en COSMAC ELF y FRED2.
Actualmente, no hay necesidad de sufrir así. Hay un emulador decente para Windows:
Emma , con un buen depurador (por cierto, emula no solo RCA Studio II, sino todos los COSMAC).
Como ensamblador, primero intenté usar el
ensamblador cruzado a18, pero, por varias razones, terminé centrándome en
asmx , que también tiene
scripts Python para generar una imagen lista para usar del cartucho (tiene la extensión .st2).
Una breve introducción al ensamblador 1802 se puede encontrar
aquí . El test.asm más simple para RCA Studio II con un bucle infinito se vería así:
.include "1802.inc" .org 400h .db 4,2 ; SYS $402 start: br start ; some code .end
Preste atención a la instrucción ".db 4,2". Esta es la dirección de la primera instrucción ejecutable, es decir ".db> (inicio), <(inicio)".
Implementación de bucle simple:
ldi 50 ; D plo r6 ; D r6 loop: dec r6 ; r6 = r6 -1 glo r6 ; r6 D bnz loop ; loop D
Usando instrucciones SKIP:
; q = 0 $FF00 , q=1 $FF loop: ghi r1 ; hi(r1) -> D lsz ; 2 , D (.. seq) req ; 0 -> Q skp ; 1 (.. inc r1) seq ; 1 -> Q inc r1 ; r1 = r1 + 1 br loop ; ...
Para practicar en un ensamblador limpio CDP1802, es conveniente usar el emulador de ensamblador en línea asm80. La extensión del archivo fuente generado debe ser .a18
Para lanzar una aplicación terminada en hardware real en la naturaleza, hay un cartucho
Multicart RCA Studio II 40th Anniversary . No lo tenía, pero tnt23 rehizo uno de los cartuchos disponibles con un juego para el chip EEPROM AT28C16 (2k x 8) instalado en el zócalo.
Entonces, para correr sobre la pieza de hierro, inserté el chip en el programador cada vez, lo flasheé, lo reorganicé en un cartucho convertido, encendí la consola. Y así cada vez.
INTRO NO SHADERS
Para desarrollar la plataforma, escribí 256 bytes de introducción (presentado en
Chaos Constructions'2018 en el concurso de
introducción Tiny ).
A diferencia de, por ejemplo,
Vectrex , donde puedes obtener una imagen espectacular incluso dibujando una curva o desde
Videopac , donde la ROM ya tiene un conjunto de imágenes de pequeños hombres, aquí tenemos una situación triste: ordinaria, familiar para todos, gráficos rasterizados, pero en blanco y negro y resoluciones a continuación en ninguna parte (64x32). En ROM, no solo hay imágenes, sino incluso caracteres. Sonido, y eso está limitado a un chirrido de 625Hz.
Por lo tanto, la música, todo tipo de plasmas típicos, luces y, en general, todo lo que implica contornos no cuadrados se ha cancelado. El texto en cualquier forma también fue cancelado: no habría suficiente espacio para las letras.
Como resultado, se decidió a) desplazarse b) algo que se repite c) con diferentes velocidades. Resultó así:
Como se mencionó anteriormente, no hay desplazamiento de hardware en el controlador de video. Sin embargo, la baja resolución y el blanco y negro no solo tienen inconvenientes, sino también ventajas: sobrescribir menos bytes.
Me desplacé línea por línea, usando el comando shlc (desplazamiento a la izquierda con guión): cuando se ejecuta en un bucle, resulta que el bit más a la izquierda del siguiente byte se desplaza a la izquierda y no desaparece, pero se coloca en el indicador de acarreo (DF). En consecuencia, el siguiente shlc en un bucle lo recoge y lo coloca en el byte a la izquierda. Resulta un desplazamiento simple de toda la línea, de los cuales ocho se desplazarán en un ciclo (ya que es conveniente tomar patrones de nubes y casas byte a byte)
... scrollret: sep r3 ; return from subroutine ; scroll: ; set lines counter ldi LINES ; const -> D plo r10 ; D -> Rn.0 nextline: ; set bytes counter ldi BYTES_PER_LINE ; const -> D plo r7 ; D -> Rn.0 ; set carry to scroll glo r12 ; Rn -> D shr ; get one bit to set carry plo r12 ; D -> Rn.0 (save shifted byte) nextbyte: ldx ; Rx -> D shlc ; D = D << 1 (carry -> DF) stxd ; D -> M(Rx), Rx-- dec r7 ; Rn-- glo r7 ; Rn -> D bnz nextbyte dec r10 ; Rn-- glo r10 ; Rn -> D bnz nextline ; one line (8 bytes) scrolled, let's scroll next br scrollret ...
Tenga en cuenta que el punto de entrada a la subrutina se encuentra en la etiqueta de desplazamiento, y para volver, no solo se ejecuta sep r3, sino también br scrollret y sep r3 desde allí.
Esto se hace para dejar r14 (que es el contador de comandos dentro de la subrutina) en el estado correcto, entonces la subrutina se puede llamar una y otra vez (usando sep r14).
Por supuesto, aquí no se guardan variables durante las llamadas: todos los registros de variables son globales.
La subrutina de desplazamiento se llama dos veces en el ciclo general: cada segunda vez para casas y cada cuarta vez para nubes (se desplazan más lentamente). El ciclo general se sincroniza en la dirección inversa del haz (carretera, casas, nubes; tienen tiempo para dibujar, las estrellas son estáticas). En el caso de la carretera, solo se desplaza una línea: los bordes de la carretera simplemente se dibujan con líneas.
En aras del interés, traté de desplazar toda la pantalla; no cabe en el movimiento inverso del rayo a tiempo.
Las casas están establecidas por patrones:
... house1: .db %00000000 .db %11111111 .db %10101010 .db %11111111 .db %10101010 .db %11111111 .db %00000000 .db 1 house2: .db %00000000 .db %00011111 .db %01110101 .db %01011111 .db %01110101 .db %00011111 .db %00000000 .db 1 ...
y una tableta con un enlace a cada uno:
... commands: .db house5 .db house2 .db house1 .db house3 ...
En un ciclo, esta etiqueta se ordena secuencialmente.
A diferencia de las casas, ambas nubes, por simplicidad, representan un patrón que simplemente se desplaza cíclicamente.
Se podría ganar un cierto número de bytes debido a la salida de nubes de acuerdo con el mismo principio que las casas, así como debido a las brechas programadas entre los patrones (ahora estos son solo ceros repetitivos en los datos).
Sin embargo, el problema también es que el controlador de interrupciones utiliza algunos registros: R0, R1, R2, R8, R9, R11 no se pueden cambiar. Y almacenar variables en la memoria es una gran cantidad de bytes adicionales para escribirlas y leerlas (sin mencionar los ciclos de reloj).
Idealmente, el desplazamiento probablemente debería hacerse en el controlador de interrupciones. Sin embargo, para esto, tendría que escribir su propio controlador en lugar del estándar. Esto sería más correcto (y, por cierto, podría liberar un par de registros R), pero lo más probable, al final, todo en conjunto no encajaría en 256 bytes.
En cuanto a las estrellas, son estáticas, pero para dibujar algunos puntos que parecen localizados al azar, inesperadamente no fue tan simple:
... loop: ldn r4 ; M[Rn] -> D ani %00000010 ; D AND const -> D bdf skip ; jump if carry ldi 0 ; const -> D skip: stxd ; D -> M(Rx), Rx-- glo r4 ; Rn -> D adi 47 ; D + const -> D plo r4 ; Rn -> D glo r15 ; Rn -> D bnz loop ...
Aquí, en un ciclo, los datos se toman del BIOS, que se diluyen y se enmascaran los bits en exceso. La máscara (para ani) y el tono (para adi) se seleccionan a mano.
En cuanto al sonido, debido a la incapacidad de cambiar la frecuencia, los "pitidos" del automóvil son simplemente imitados.
Por cierto, creo que este intra es el primer trabajo de demoscene para RCA Studio II :)
EPÍLOGO
Después de Studio II, RCA lanzó varias instancias de
RCA Studio III . Diferencias en dos cosas: apareció el color (aunque la resolución no ha cambiado) y el sonido es mejor (ya no puede emitir uno, sino 255 frecuencias diferentes).
Es interesante que ambas máquinas sean compatibles entre sí en ambas direcciones, incluso mediante el uso del mismo código intermedio con el intérprete.
También se sabe que había planes para RCA Studio IV. Debería haber aumentado la resolución a 64x128, e incluso un nuevo intérprete de pseudocódigo ya estaba escrito.
En cuanto al CDP1802, este microprocesador continúa siendo producido: primero fue fabricado por Hughes, luego
Intersil (Renesas)Si desea saber más acerca de esta rama peculiar de la historia del desarrollo de la tecnología informática, le recomiendo google las palabras "
COSMAC" y "CDP1802 ".
Enlaces de sitio