Architecture et programmation RCA Studio II

"Enfin, nous arrivons à l'instruction que nous attendions tous - SEXE!"
/ de l'article sur le microprocesseur CDP1802 /




Au début des années 1970, les jeux électroniques simples tels que Pong étaient très populaires aux États-Unis (en URSS, leurs analogues sont apparus en vente dans les 5 à 10 ans). En règle générale, ces jeux n'avaient pas de microprocesseur et de mémoire au sens moderne de ces mots, mais étaient construits sur une logique rigide. En conséquence, les cartouches remplaçables n'avaient pas beaucoup de sens, et où elles se trouvaient - elles n'étaient qu'un ensemble de cavaliers comprenant le jeu souhaité.

En 1977, deux consoles sont sorties presque simultanément: Fairchild Channel F et RCA Studio II . Ce sont les premières consoles de jeu sous forme d'ordinateurs à part entière - avec un microprocesseur et des programmes de cartouches remplaçables. Le RCA Studio II, qui sera discuté, est non seulement développé par RCA , mais par une personne spécifique - Joseph A. Weisbecker (comme toute l'architecture COSMAC) .
Le premier appareil de ce type, le System 00 , également connu sous le nom de COSMAC FRED (1971), était un prototype et n'était pas produit en série.


Le processeur qu'il contient a été implémenté sur la logique habituelle (en FRED2 - sur deux puces appelées CDP1801 R et U, apparues en 1973). La RAM était de l'ordre de 256 octets - 4 ko, en outre, FRED2 avait un magnétophone intégré.


La première implémentation commerciale de l'architecture COSMAC a été l' ELF COSMAC . En 1976, ELF était positionné comme un ordinateur pour les jambons (une série d'articles a été publiée dans le magazine Popular Electronics) et était une petite carte avec des interrupteurs à bascule, des indicateurs, un microprocesseur CDP1802 (le même 1801, mais déjà dans une puce) et 256 octets de RAM. Pour lui, il y avait des cartes d'extension supplémentaires qui permettaient d'afficher des graphiques sur le moniteur (en utilisant la puce CDP1861), un clavier externe et un magnétophone étaient connectés. Sur la base des ELF avec extensions, ELF II et VIP sont apparus. Dans les ROM COSMAC, il y avait une machine virtuelle appelée CHIP-8, affûtée pour les jeux primitifs (commandes pour sortir et déplacer les sprites logiciels, générer des nombres aléatoires, etc.) Il y avait d'autres ordinateurs et terminaux primitifs basés sur cette architecture.


Tous ces appareils étaient des prédécesseurs directs de RCA Studio II et ont une architecture matérielle et logicielle extrêmement proche.

RCA Studio II est sorti en 1977 et a ensuite été vendu pour 150 $ (600 $ pour l'argent actuel). Comme cela arrive souvent, le premier sur le marché n'est pas forcément le plus performant. En 2008, le magazine PC World a reconnu cette console comme la pire console de jeu de tous les temps (ce qui, en principe, n'est pas loin de la vérité) .Une image en noir et blanc de carrés, l'absence de joysticks (au lieu de deux champs de 10 boutons) et une douzaine de jeux - pour ne pas dire plus acheteurs satisfaits.


De plus, tous les jeux (intégrés et vendus sur cartouches) ont été écrits dans le pseudo-code de la machine virtuelle ST2 (la même idée qu'avec CHIP-8 dans les COSMAC), ce qui l'a rendu très lent.

RCA a réussi à libérer environ 64000 unités de RCA Studio II, sans compter les clones qui sont apparus plus tard (Toshiba Visicom, Conic M-1200, etc.) Avec l'avènement d' Atari VCS , le RCA Studio II et Fairchild Channel F obsolètes ont instantanément abandonné le combat.

CPU


En tant que fabricant de puces, RCA a choisi son propre produit comme processeur de décodeur - le microprocesseur RCA CDP1802 , fonctionnant à 1,78 MHz et fabriqué à l'aide de la technologie CMOS.


Son prédécesseur était le CDP1801, un processeur à deux puces (entièrement compatible avec 1802):


Le CDP1802 est connu pour sa version résistante aux radiations (silicium sur saphir), dans laquelle il était utilisé, par exemple, à la station interplanétaire Galileo , volant vers Jupiter dans les années 1990 (il y avait 6 de ces processeurs), ainsi que dans MAGSAT .

Le processeur a un schéma d'utilisation de registre assez délicat. Il possède un accumulateur D 8 bits et seize registres 16 bits - R0..RF (R0-R15), chacun pouvant devenir un pointeur d'instruction, en fonction du contenu du registre P 4 bits (pointant vers l'un des R), modifiable Équipe SEP Rn. En d'autres termes - il n'y a pas un seul PC dans le processeur!


De plus, n'importe lequel de R0 ... R15 peut devenir index (adresse). La sélection est déterminée sur la base de la valeur dans le registre 4 bits X (modifié par la commande SEX Rn), après quoi le R sélectionné est considéré comme indexé pour certaines commandes.

Le registre d'adresses pour DMA est toujours R0. A l'intérieur de l'interruption, le compteur d'instructions est R1.

Il existe un registre T à 8 bits, qui est utilisé pour y enregistrer automatiquement les registres X et P lorsqu'une interruption se produit. Les interruptions sont activées en définissant le drapeau IE Interrupt Enable via les commandes RET ou DIS.

Les registres 4 et I et N contiennent l'instruction courante exécutée par le processeur.

Il existe un registre des drapeaux - DF. Plus précisément, un drapeau, car il est à un chiffre et ne contient qu'un drapeau de report.

De plus, le processeur possède un port de sortie à bit unique Q, dont l'état est modifié par les commandes SEQ et REQ.

Comme dans de nombreux processeurs de cette génération, la pile au sens habituel est absente ici (il n'y a ni commandes PUSH, POP, ni pointeur de pile) et, si nécessaire, est implémentée par les instructions existantes.

Il n'y a pas non plus d'instructions traditionnelles pour appeler des routines. La transition vers le sous-programme s'effectue à l'aide de l'instruction SEP Rn qui, je le rappelle, fait du registre Rn indiqué un compteur de commandes. Pour revenir, la même instruction SEP est utilisée, mais avec un registre qui était le compteur de commandes avant l'appel. Ou (dans une version plus universelle mais plus lente) MARK et RET sont utilisés.

En plus des sauts conditionnels et inconditionnels traditionnels (en passant - ils sont tous absolus), il existe plusieurs instructions SKIP qui, lorsque la condition est remplie, sautent la prochaine instruction SKIP (deux octets). SKIP inconditionnel est également fourni.

Le processeur 1802 est souvent considéré comme l'un des premiers processeurs RISC. Cependant, dans le même contexte, il est fait mention, par exemple, du 6502, ainsi que de quelques autres. Il est certain que l'architecture n'est pas tout à fait ordinaire et, du point de vue de la programmation, provoque des sentiments mitigés. D'une part, il existe jusqu'à seize registres 16 bits. D'un autre côté, leur contenu directement ne peut être réduit et augmenté que de un. Par exemple, mettre une constante dans Rn ressemble à ceci:

ldi $01 ; const -> D plo r6 ; D -> R6.0 ldi $02 ; const -> D phi r6 ; D -> R6.1 

Par conséquent, la part du lion du code déplace les octets d'avant en arrière.

Des transitions par condition, il n'y a, en effet, qu'une transition vers zéro (seule la situation où 0 est dans l'accumulateur D) et l'indicateur de transfert sont considérés. Les boucles typiques sont les suivantes:

 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 

Toutes les instructions arithmétiques et logiques ne fonctionnent qu'avec la batterie D.

En plus du port à un bit contrôlé par SEQ / REQ, il existe également un port à quatre bits contrôlé par les commandes OUT / INP. Malheureusement, il n'est pas utilisé dans RCA Studio II.

MEMOIRE


Il y a: 2 Ko de ROM (BIOS + cinq jeux intégrés) 512 octets de RAM (la moitié est réservée à la vidéo)
Carte mémoire

 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  (  ) 

Il est nécessaire de noter spécifiquement que pour les jeux et programmes sur cartouches, seule une partie du BIOS est disponible - celle qui contient SP2 (inutile, en gros), les images des nombres de 0 à 9 et le gestionnaire d'interruption standard pour la vidéo.

VIDÉO


Pour les graphiques, la puce RCA CDP1861 est utilisée - le soi-disant "Pixie".

Le RCA Studio II standard a une sortie standard avec seulement une antenne (RF), cependant, les gens le remodèlent en composite afin que la qualité soit meilleure (j'ai presque écrit "pour une meilleure reproduction des couleurs" :))

Techniquement, le contrôleur vidéo offre une résolution maximale de 64x128 en deux couleurs (noir et blanc). Cependant, cela nécessite 1024 octets de mémoire vidéo et dans Studio II, la quantité totale de RAM est de 512 octets. Par conséquent, la résolution est de 64 x 32 (ce qui nécessite 256 octets). La résolution horizontale (64) est fixe. Sur une ligne de 64 pixels, 8 octets sont toujours affichés, et cela se produit pendant 14 cycles de processeur.

Le gestionnaire d'interruption du BIOS est utilisé pour afficher la mémoire (900 $ - 9 $ fff) à l'écran. L'interruption est déclenchée par le contrôleur vidéo et se produit 60 fois par seconde (NTSC). Le processeur BIOS effectue toutes les opérations nécessaires - le programme exécutable n'a qu'à changer la mémoire vidéo, dans laquelle chaque bit correspond directement à un point noir ou blanc (de gauche à droite, de haut en bas).


Cependant, rien ne vous empêche d'écrire votre propre gestionnaire. Le cas le plus simple est la résolution de 64x128, car il est naturel pour un contrôleur vidéo. Pour lui, dans le gestionnaire, il suffit d'écrire l'adresse de la mémoire vidéo dans R0 (d'où proviendront les données de l'écran) et les octets commenceront à s'afficher via le DMA eux-mêmes, remplissant le cadre. La situation est plus compliquée avec des résolutions verticales autres que 128. Là, vous devez entrer des délais et dupliquer données en changeant R0 (voir la description de cdp1861 et la source du BIOS).

En principe, vous pouvez même créer une résolution verticale variable, ne rien afficher sur une partie de l'écran et spécifier également la ROM, pas la RAM (ou partiellement la ROM et partiellement la RAM) comme mémoire vidéo. Vous pouvez également implémenter le défilement vertical, en modifiant l'initiale dans R0 Adresse à partir de laquelle les données commencent à être envoyées au contrôleur.

Notez qu'à la sortie INT du contrôleur vidéo, l'unité apparaît deux lignes avant que le faisceau n'atteigne la zone visible. Par conséquent, le gestionnaire d'interruption démarre généralement avec un délai qui vous permet de commencer à afficher la mémoire à l'heure.


Le contrôleur vidéo possède également une sortie EFX, sur laquelle 0 apparaît pour 4 lignes avant que le faisceau n'apparaisse dans la zone visible, puis pour les 4 dernières lignes de cette zone. La sortie EFX est connectée au processeur EF1 et son état peut être vérifié avec la commande B1 (BN1).

L'attente typique d'un faisceau de retour le long du cadre est implémentée comme suit:

 ... delay: bn1 delay ; wait for EFX in video chip ... 

Comme indiqué ci-dessus, dans la ROM, il n'y a pas d'images de lettres et de signes. Cependant, il y a encore des chiffres (après tout, dans les jeux intégrés, vous devez en quelque sorte afficher les points et le numéro du joueur). Cependant, même ici, ils ont réussi à économiser:


Comme vous pouvez le voir, les nombres sont collés ensemble de sorte que les autres sont obtenus à partir de plusieurs adjacents.

SON


Disons simplement qu'il y a du son. Mais pas plus. Le NE555 est relié au port de sortie simple bit du CDP1802 avec un cerclage, puis il est tout connecté au haut-parleur intégré dans le décodeur. Lorsqu'une unité est fournie à l'entrée RST NE555 (par la commande du processeur SEQ), elle commence à émettre un bip à une fréquence de 625 Hz. Lorsque zéro (par la commande REQ) - le bip s'arrête. En fait, c'est tout. Cependant, il existe toujours un condensateur grâce auquel, au début du grincement, la fréquence diminue progressivement de moitié en 0,4 seconde (c'est-à-dire que des crissements supplémentaires sont obtenus).


Dans le gestionnaire d'interruption du BIOS standard, en plus de la partie responsable de la vidéo, il y a un morceau qui vérifie le contenu d'une cellule de mémoire spécifique et, s'il n'y a pas zéro, active le grincement et commence à diminuer cycliquement le contenu de la cellule 08CD $ (lorsque le zéro est atteint, le grincement est désactivé). Ainsi, vous ne pouvez pas vous soucier de l'auto-enregistrement dans le port, mais simplement définir la durée du grincement et cela se produira en arrière-plan, sans arrêter le programme:

  ldi $8cd & $ff plo rf ldi 250 ;   str rf ... 

La même chose peut également être effectuée manuellement (après avoir désactivé les interruptions):

 ;   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 


PROGRAMMES


Dans les années 1970, un peu plus d'une douzaine de jeux et plusieurs autres programmes ont été écrits (principalement par RCA lui-même). Presque tous ont été écrits non pas en assembleur, mais en pseudo - code - dans la ROM de la console, il y a un interpréteur-machine virtuelle spécial ST2. Il est difficile de dire exactement ce qui a motivé une telle décision. Très probablement, l'idée était d'économiser de la mémoire - les jeux s'avèrent vraiment beaucoup moins volumineux. En général, les oreilles ST2 se développent à partir d'une machine virtuelle similaire appelée CHIP-8 , utilisée dans les COSMAC. Bien que les deux machines virtuelles ne soient pas compatibles l'une avec l'autre, déjà dans les années 2000, l'interpréteur CHIP-8 pour RCA Studio II a été écrit. Étant donné l'extrême similitude des architectures, il n'est pas surprenant que, comme l'écrit l'interprète, des jeux avec des COSMAC qui ne nécessitaient pas beaucoup de mémoire aient démarré sans problème sur RCA Studio II.


Hélas - les VM sur une telle architecture fonctionnent très lentement, ce qui laisse une empreinte indélébile sur les jeux eux-mêmes. Plus tard, en 2013, Paul Robson a écrit une douzaine de jeux supplémentaires - déjà en assembleur et les a distribués avec la source.

DÉVELOPPEMENT


Initialement, selon des témoins, le développement de RCA Studio II a été réalisé même sans assembleur - sur COSMAC ELF et FRED2.

Actuellement, il n'est pas nécessaire de souffrir comme ça. Il y a un émulateur décent pour Windows - Emma , avec un bon débogueur (au fait, il émule non seulement RCA Studio II, mais tous les COSMAC).


En tant qu'assembleur, j'ai d'abord essayé d'utiliser le cross-assembler a18, mais, pour un certain nombre de raisons, j'ai fini par me concentrer sur asmx , qui a également des scripts Python pour générer une image prête à l'emploi de la cartouche (il a l'extension .st2).

Une brève introduction à l'assembleur 1802 peut être trouvée ici . Le test.asm le plus simple pour RCA Studio II avec une boucle infinie ressemblerait à ceci:

  .include "1802.inc" .org 400h .db 4,2 ; SYS $402 start: br start ; some code .end 

Faites attention à l'instruction ".db 4,2". Il s'agit de l'adresse de la première instruction exécutable, c'est-à-dire ".db> (début), <(début)".

Implémentation de boucle simple:

  ldi 50 ;    D   plo r6 ;    D     r6 loop: dec r6 ; r6 = r6 -1 glo r6 ;     r6   D bnz loop ;    loop    D   

Utilisation des instructions 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 ;  ... 

Pour vous entraîner à utiliser l'assembleur CDP1802 pur, il est pratique d'utiliser l'émulateur d'assembleur en ligne asm80. L'extension du fichier source généré doit être .a18

Pour lancer une application terminée sur du matériel réel dans la nature, il existe une cartouche multicartes RCA Studio II 40th Anniversary . Je ne l’avais pas, mais tnt23 a refait une des cartouches disponibles avec un jeu pour la puce EEPROM AT28C16 (2k x 8) installé dans le socket.


Donc, pour courir sur le morceau de fer, j'ai inséré la puce dans le programmateur à chaque fois, je l'ai flashée, je l'ai réorganisée dans une cartouche convertie, j'ai allumé la console. Et donc à chaque fois.



INTRO NO SHADERS



Afin de développer la plateforme, j'ai écrit 256 octets d'intro (présentés lors de Chaos Constructions'2018 dans le cadre du concours d' introduction de Tiny ).

Contrairement, disons, à Vectrex , où vous pouvez obtenir une image spectaculaire même en dessinant une courbe ou à partir de Videopac , où la ROM contient déjà un ensemble d'images de petits hommes, nous avons ici une situation triste - ordinaire, familière à tout le monde, des graphiques raster, mais en noir et blanc et les résolutions ci-dessous nulle part (64x32). En ROM, il n'y a pas que des images, mais même des personnages. Son - et qui est limité à un couinement à 625 Hz.

Ainsi, la musique, toutes sortes de plasmas typiques, les lumières et en général tout ce qui implique des contours non carrés a été annulé. Le texte sous quelque forme que ce soit a également été annulé - il n'y aurait pas assez d'espace pour les lettres.

En conséquence, il a été décidé a) de faire défiler b) quelque chose qui se répète c) avec des vitesses différentes.


Comme mentionné ci-dessus, il n'y a pas de défilement matériel dans le contrôleur vidéo. Cependant, la basse résolution et le noir et blanc ont non seulement des inconvénients, mais aussi des avantages - écrasant moins d'octets.

J'ai fait défiler ligne par ligne, en utilisant la commande shlc (décalage gauche avec césure) - lorsqu'il est exécuté en boucle, il s'avère que le bit le plus à gauche de l'octet suivant est décalé vers la gauche et ne disparaît pas, mais est placé dans le drapeau de report (DF). Par conséquent, le shlc suivant dans une boucle le prend et le place dans l'octet de gauche. Il s'avère un simple défilement de la ligne entière, dont huit défileront dans un cycle (car il est commode de prendre des motifs de nuages ​​et de maisons octet par octet)

 ... 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 ... 

Notez que le point d'entrée du sous-programme est situé sur l'étiquette de défilement, et pour revenir, non seulement sep r3 est exécuté, mais d'abord br scrollret et sep r3 à partir de là.

Ceci est fait afin de laisser r14 (qui est le compteur d'instructions à l'intérieur du sous-programme) dans l'état correct, puis le sous-programme peut être appelé encore et encore (en utilisant sep r14).

Bien sûr, aucune variable n'est enregistrée pendant les appels ici - tous les registres de variables sont globaux.

Le sous-programme de défilement est appelé deux fois dans la boucle générale - une fois sur deux pour les maisons et une fois sur quatre pour les nuages ​​(ils défilent le plus lentement). Le cycle général est synchronisé dans le sens inverse du faisceau (route, maisons, nuages ​​- ont le temps de dessiner, les étoiles sont statiques). Dans le cas de la route, une seule ligne défile - les bords de la route sont simplement tracés avec des lignes.

Par souci d'intérêt, j'ai essayé de faire défiler tout l'écran - il ne rentre pas dans le mouvement inverse du faisceau dans le temps.

Les maisons sont définies par des motifs:

 ... 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 ... 

et une tablette avec un lien vers chacun:

 ... commands: .db house5 .db house2 .db house1 .db house3 ... 

Dans un cycle, cette étiquette est triée séquentiellement.

Contrairement aux maisons, les deux nuages, pour simplifier, représentent un motif qui défile simplement de façon cyclique.

Un certain nombre d'octets pourraient être gagnés en raison de la sortie des nuages ​​selon le même principe que les maisons, ainsi qu'en raison des écarts programmés entre les modèles (maintenant ce ne sont que des zéros répétitifs dans les données).

Cependant, le problème est également que certains registres sont utilisés par le gestionnaire d'interruption - R0, R1, R2, R8, R9, R11 ne peuvent pas être modifiés. Et stocker des variables en mémoire représente beaucoup d'octets supplémentaires pour les écrire et les lire (sans parler des cycles d'horloge).

Idéalement, le défilement devrait probablement être effectué dans le gestionnaire d'interruption. Cependant, pour cela, vous devrez écrire votre propre gestionnaire au lieu du gestionnaire standard. Ce serait plus correct (et, incidemment, pourrait libérer quelques registres R), mais très probablement, au final, tout ne rentrerait pas dans 256 octets.

Quant aux étoiles, elles sont statiques, mais pour dessiner quelques points qui semblent aléatoires, ce n'était pas si 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 ... 

Ici, dans un cycle, les données sont extraites du BIOS, qui sont affinées et les bits en excès sont masqués. Le masque (pour ani) et la hauteur (pour adi) sont sélectionnés à la main.

Quant au son, en raison de l'impossibilité de changer la fréquence, les «bips» de la voiture sont simplement imités.

Soit dit en passant - je pense que ce intra est la première œuvre de démoscène pour RCA Studio II :)

ÉPILOGUE


Après Studio II, RCA a publié plusieurs instances de RCA Studio III . Différences en deux choses - la couleur est apparue (alors que la résolution n'a pas changé) et le son est meilleur (vous pouvez déjà émettre non pas une, mais 255 fréquences différentes).


Il est intéressant de noter que les deux machines sont compatibles entre elles dans les deux sens, y compris grâce à l'utilisation du même code intermédiaire avec l'interpréteur.

Il est également connu qu'il y avait des plans pour RCA Studio IV. La résolution aurait dû être augmentée à 64x128, et même un nouvel interpréteur de pseudo-code avait déjà été écrit.

Quant au CDP1802, ce microprocesseur continue d'être produit - d'abord il a été fabriqué par Hughes, puis Intersil (Renesas)

Si vous voulez en savoir plus sur cette branche particulière de l'histoire du développement de la technologie informatique, je recommande google les mots " COSMAC" et "CDP1802 ".

Liens annexes


Source: https://habr.com/ru/post/fr422277/


All Articles