Architektur und Programmierung Fairchild Channel F.

"Channel F Homebrew wäre wie das Programmieren von Sprites über Hardware-Jumper ..."
/ chadtower, atariage forum /



Die Fairchild Channel F -Spielekonsole, auch bekannt als VES, erschien im November 1976. Im Gegensatz zu seinen Vorgängern wie Ping-Pong, Tennis (in derselben Reihe - der sowjetische "Videosport") hatte es einen sehr signifikanten Unterschied - das Vorhandensein eines Mikroprozessors und von Kassetten mit Programmen. Zuvor wurden Spiele in Konsolen nach strenger Logik implementiert - das Programm im modernen Sinne fehlte dort.

Fairchild Channel F wurde bis 1983 veröffentlicht. In dieser Zeit wurden mehr als eine Viertelmillion dieser Konsolen verkauft und etwa 30 bis 40 Spiele veröffentlicht , von denen einige bereits in den 2000er Jahren waren.

In Bezug auf die Überlegenheit bei der Verwendung eines Mikroprozessors ist anzumerken, dass RCA Studio II, über das ich in einem früheren Artikel gesprochen habe, nur ein paar Monate zu spät war, sich jedoch als wesentlich schwächer als Channel F herausstellte, weshalb es beim Verkauf fehlschlug. Allerdings erschien der Auftritt, weniger als ein Jahr später, Atari VCS - und ersetzte Channel F. vom Markt.

Die Entwicklung von Fairchild_Channel_F als solche war nicht. In System II und mehreren Klonen wie Saba Videoplay 2 (1979) bestanden die Unterschiede hauptsächlich im Körper, in den Joysticks (übrigens verstanden sie alle, mit Ausnahme der üblichen Positionen, der Drehung des Knopfes) und der Anzahl der Chips. Architektonisch war alles fast identisch.

Was ist Kanal F?

CPU


Der Prozessor wurde in den Traditionen dieser Zeit von derselben Fairchild-Firma wie die Konsole selbst hergestellt und heißt F8 en.wikipedia.org/wiki/Fairchild_F8 . Dies ist ein 8-Bit-Prozessor aus dem Jahr 1974, der mit einer Frequenz von 1,8 MHz arbeitet (ein Befehl benötigt 1 bis 6 Taktzyklen).



Es kann jedoch nur mit einer Dehnung als Mikroprozessor bezeichnet werden, da dieser Prozessor aus zwei Chips besteht - einem 3850CPU-Computergerät, das ALU, eine Batterie, 64 Byte SRAM, die zur Ausführung von Anweisungen erforderliche Logik, zwei Ports (es gibt keinen Adressbus!) Und 3851PSU (programmierbar) enthält Speichereinheit), die 1 KB ROM (für das BIOS verwendet), einen Befehlszeiger, Speicheradressierungsschemata, Interrupts, einen Timer (Interrupts und ein Timer werden in Kanal F nicht speziell verwendet) enthält.

Später erschien der F3859-Chip, der CPU und Netzteil auf demselben Chip und Mostek 3870 kombinierte - eine leicht verbesserte Version, die bis in die 1990er Jahre veröffentlicht wurde. Dies ist jedoch eine andere Geschichte. Interessanterweise wird der F8 manchmal als Mikrocontroller bezeichnet (insbesondere aufgrund des Vorhandenseins eines Timers und von Ports) und als Vorfahr der Intel MCS-48-Familie (8048) bezeichnet.

Neben Kanal F wurde der F8-Prozessor auch im VideoBrain- Computer und im CompuChess- Schachcomputer verwendet. Im Allgemeinen ist es überraschend, dass es nur sehr wenige Informationen zu diesem Prozessor gibt. Mit Ausnahme einiger Beschreibungen von Fairchild und des Quellcodes mehrerer Spiele und Beispiele speziell für Channel F gibt es nichts mehr. Es scheint, dass dieser Prozessor nirgendwo anders verwendet wurde, was unglaublich erscheint (da seine erweiterten Versionen schon seit einiger Zeit veröffentlicht wurden). Ich gehe davon aus, dass alle anderen Geräte, bei denen es verwendet wurde, für militärische Zwecke verwendet wurden.

Nun ein wenig zu den Funktionen des Prozessors. Denken Sie über den Satz und die Funktionen seiner Register nach. Ich denke, dies ist eine der verwirrendsten Architekturen, die es zu dieser Zeit gab (moderne mögen sich wahrscheinlich ausdehnen, aber der Vergleich wird falsch sein, weil sie für Compiler konzipiert sind. Lebende Menschen haben mit F8 gearbeitet).

Es gibt viele Register im Prozessor. Neben der 8-Bit-Batterie A und dem Flag-Register W (I, O, Z, C, S) gibt es auch ein „Scratchpad“ - 64 8-Bit-Zellen mit verschiedenen Funktionen.

Die ersten neun Zellen werden als Allzweckregister R0-R8 in Befehlen wie 'lr a, 7 "verwendet (Laden Sie den Inhalt des Registers R7 in die Batterie). Beachten Sie, dass der Buchstabe R nicht angezeigt wird - nur die Registernummer wird geschrieben. Was genau ist gemeint, die Nummer oder Die Zahl sollte aus dem Kontext ersichtlich sein. Sagen wir, im Fall der lr-Anweisung kann es einfach keine Zahlen geben. Und wenn zum Beispiel „li 7“ (eine Konstante in die Batterie laden), dann ist es genau eine Zahl, kein Register.

Die Zellen 9, 10-11 (H), 12-13 (K), 14-15 (Q) dienen zum Speichern anderer Register in verschiedenen Situationen, z. B. beim Aufrufen von Unterprogrammen.

Auf die Register R16-R63 kann nur über ein spezielles ISAR-Indexregister (Indirect Scratchpad Address Register) als sechs Acht-Byte-Puffer zugegriffen werden, die aus den Zellen 16-23, 24-31, 32-39, 40-47, 48-55, 56-63 gebildet werden .

Das Sechs-Bit-ISAR ist in zwei Teile von 3 Bits unterteilt. Wenn der ISAR um eins erhöht oder verringert wird, sind nur die unteren 3 Bits betroffen - d. H. Die Adressierung erfolgt innerhalb eines der sechs genannten Acht-Byte-Puffer (gleichzeitig kann das Ende des Puffers durch die speziellen bedingten br7-Verzweigungsbefehle verfolgt werden).

clr ; 0 -> A ; set ISAR to full address Ox27 (octal 27) lisu 2 ; buffer N2 lisl 7 ; index within buffer N2 loop: lr d,a ; A-> buffer N2[index], than decrement ISAR (27, 26, 25, ... ) br7 loop ; go further if low part of ISAR contains 7 (end of buffer N2). if not, go loop again 

In diesem Fall ist "d" in der Anweisung "lr d, a" nicht der Name des Registers, sondern ein Zeichen dafür, dass der ISAR reduziert werden muss ("i" - erhöhen, "s" - unverändert lassen).

Es gibt eine andere Möglichkeit der indirekten Adressierung - über das DC0-Register (Datenzähler):

  dci data_addr ; data_addr -> DC0 lm ; [data_addr] -> A, DC0 + 1 -> DC0 ... data_addr: db 0,1,2,3,... 

Wenn Sie Daten von einem Speicherbereich in einen anderen übertragen müssen, wird zusätzlich der Befehl xdc verwendet, der den Inhalt der Register DC0 und DC1 vertauscht. Das heißt, Wir lesen von der Adresse, auf die DC0 zeigt, machen dann xdc und schreiben an die Adresse, auf die DC1 jetzt zeigt. Dann wieder xdc usw. Das heißt, DC1 ist eine Art Schattenregister zum Speichern einer Kopie von DC0. Ein direkter Zugriff darauf (mit Ausnahme des Befehls xdc) ist nicht möglich.

Die obigen Beispiele veranschaulichen nur einen Teil der Möglichkeiten zur Adressierung, tatsächlich gibt es mehr davon.

Auch in F8 gibt es vier Ports - 0,1,4,5, in die Sie mit dem Befehl out schreiben und mit dem Befehl in lesen können. In Kanal F werden Ports zur Ausgabe von Grafiken, Sound und zum Lesen des Joystick-Status verwendet.

Ich werde nicht auf andere Anweisungen wie Arithmetik, Übergänge usw. eingehen - sie sind ziemlich Standard. Ich stelle nur fest, dass die Auswahl an Registern, über die Sie Aktionen ausführen können, sehr begrenzt ist, sodass der Code schnell wächst, da Werte ständig hin und her verschoben werden müssen.

Es gibt keine Subtraktion (es gibt nur Addition). Die Anweisungen zum Dekrementieren (ds) und Inkrementieren (inc) pro Einheit sind asymmetrisch. ds funktioniert nur mit den Registern r0-r8, inc - nur mit der Batterie.

Ein bedingungsloser Sprung verdirbt die Batterie.

Ein Beispiel für eine reguläre Schleife:

  li 25 ; (r4) number of iterations lr 4,a next: ds 4 ; r4-- bnz next ; until r4 == 0 

Routinen


Da F8 keinen Hardware-Stack hat, gibt es Schwierigkeiten mit verschachtelten Unterprogrammaufrufen. Ein normaler Anruf und eine normale Rückgabe sehen folgendermaßen aus:

  ; ...code pi sub ; Pushes address of next instruction to PC1 ; address of sub is stored in PC0 (jump to subroutine) ; ...code continues sub: ; ... often used code pop ; Move return address from PC1 to PC0 

Hier ist PC0 ein regulärer Befehlszeiger. PC1 - das sogenannte "Stapelregister". Es hat nichts mit dem Stack zu tun, nur PC0 wird darin gespeichert, wenn das Unterprogramm aufgerufen wird.

Wenn ein anderes Unterprogramm von sub aufgerufen wird, wird die Rücksprungadresse überschrieben und muss kompliziert sein (speichern Sie die erste Rücksprungadresse in Register K):

  prog: ; ...do something... pi sub1 ; Address of next instruction stored in PC1 ; sub1 is stored in PC0 (jump to subroutine) ; ...do more... sub1: lr k,p ; Copy PC1 to K, original jump address to K ; ...do something... pi sub2 ; Pushes address of next instruction to PC1 ; sub1 is stored in PC0 (jump to subroutine) ; ...do more... pk ; Store address of next instruction in PC1 ; Copy value in K to PC0 (jump back to main) sub2: ; ...do something... pop ; Move return address from PC1 to PC0 

Wenn Sie auch eine dritte Verschachtelungsebene benötigen, wird alles völlig traurig (im BIOS gibt es dafür sogar zwei spezielle Routinen - Pushk und Popk).

Die allgemeine Empfehlung besteht darin, zu versuchen, Unterprogrammaufrufe durch Makros zu ersetzen. Natürlich, wenn es keine strengen Einschränkungen für die Größe des Codes gibt.

In F8 gibt es keinen Hardware-Stack. Bei Bedarf wird es programmgesteuert implementiert - über ISAR und Puffer.

Das Schreiben in den Arbeitsspeicher ist nicht sehr relevant (mangels eines), sieht aber so aus:

  li $FF ; set value dci $3800 ; set target address st ; write 

Die Erinnerung


Obwohl dies etwas seltsam klingt, gibt es in Fairchild Channel F keinen RAM. Die vorhandenen zwei Kilobyte Videospeicher (MK4027) werden nicht im Adressraum angezeigt, und tatsächlich sind sie nicht lesbar, sondern werden über Ports beschrieben. Die Register des Mikroprozessors, selbst 64, werden für RAM kaum als korrekt angesehen.

Das ausführbare Programm wird in austauschbaren ROM-Kassetten gespeichert, die meist eine Kapazität von 2 KB haben (einige moderne Spiele verwenden 3 KB-, 4 KB- und 5 KB-Kassetten). Darüber hinaus gibt es einen eingebauten Prozessorchip, 1 KB ROM ROM, der ein einfaches Spiel wie Tennis, einige nützliche Routinen und Bilder mehrerer Charaktere enthält.

Im Adressraum befindet sich das BIOS von $ 0000 bis $ 07ff, das Kassetten-ROM - von $ 0800.

Grafik


Die grafischen Fähigkeiten von Kanal F sind sehr primitiv, da es dort einfach keinen Videocontroller in Form eines separaten Chips gibt - alles wird nach der üblichen Logik wie Schieberegistern, Gattern und Operationsverstärkern implementiert. Es ist ziemlich ungewöhnlich, dass verschiedene Quellen unterschiedliche Auflösungen erwähnen, und es gibt viele Optionen. Tatsache ist, dass die verfügbaren 2 Kilobyte Videospeicher eine Auflösung von 128 x 64 bedeuten, aber in Wirklichkeit ist dies weit davon entfernt. Erstens hängt vieles davon ab, welcher Bereich des auf diesem bestimmten Fernsehgerät erzeugten Bildes sichtbar ist (weshalb die ersten 4 Spalten überhaupt nicht offiziell verwendet werden). Zweitens werden die letzten Spalten unter der Palette verwendet. Drittens wird ein Teil des Speichers überhaupt nicht verwendet.

Infolgedessen kann die tatsächliche Auflösung grob auf 95 x 58 Pixel mit 8 Farben geschätzt werden (was jedoch viel besser ist als RCA Studio II mit seinen Schwarzweiß-64 x 32).

Die meisten Konsolen sind in der NTSC-Version verfügbar, es gibt jedoch auch PAL. Es gibt keine praktischen Unterschiede, wie sie sagen (die Anzahl der Zeilen ist gleich).

Im Wesentlichen können Sie mit einem so einfachen Bügeleisen nur Punkte auf dem Bildschirm zeichnen. Obwohl die Gesamtzahl der angezeigten Farben 8 beträgt, können nur vier innerhalb einer Zeile angezeigt werden (Sie können dies willkürlich als Palette bezeichnen). Die Palette wird für jede Zeile einzeln festgelegt und an einem ziemlich seltsamen Ort gespeichert - in den Spalten 125 und 126 jeder Zeile (die sich auf jeden Fall außerhalb des sichtbaren Bereichs befinden). Das Ändern der Palette erfolgt jeweils durch Zeichnen von Pixeln in diesen beiden Spalten.


(Der tatsächlich auf dem Bildschirm sichtbare Videospeicherbereich und der Bereich, in dem die Palette festgelegt ist, werden gelb hervorgehoben.)

Wie oben erwähnt, gibt es nur eine Möglichkeit, Daten in den VRAM zu schreiben - über die Ports. Dies gibt die Farbe, Spalte, Zeile an:

X wird in Port 4 geschrieben, Y in Port 5, die Farbe in Port 1, wonach die Daten übertragen werden, indem eine Konstante in Port 0 geschrieben wird:

  ; set color (2 bit per pixel) li $00 ; color ($00 = green, $40 = red, $80 = blue, $C0 = background) outs 1 li 104 ; X com outs 4 ; set the row li 61 ; Y com outs 5 ; transfer data to VRAM li $60 outs 0 li $50 outs 0 ; wait for update lis 6 delay: ai $ff bnz delay 

Es ist eine Verzögerung erforderlich, damit alles aufgezeichnet werden kann, da sonst möglicherweise nicht der nächste Punkt gezogen wird. In der offiziellen Version wird der Spalte und Zeile noch 4 hinzugefügt (der Einfachheit halber weggelassen).

Das Füllen des gesamten Bildschirms mit Punkten (in einer Schleife) dauert somit etwa eine Sekunde. Es ist wichtig zu beachten, dass es neben der extrem langsamen Bildschirmaktualisierung auch die Tatsache gibt, dass es keine Möglichkeit gibt, darauf zu warten, dass der Strahl durch den Rahmen zurückkehrt. Dementsprechend geht auch ein kleines Neuzeichnen zwangsläufig mit einem Flackern einher.

Nun zur Palette. Genau genommen gibt es für jede Linie zwei Modi: Schwarz und Weiß (wenn der Hintergrund schwarz und der Vordergrund nur weiß ist, unabhängig davon, welches Pixel gezeichnet wird) und Farbe.

Im Vordergrundfarbmodus gibt es immer drei - Rot, Grün, Blau (RGB). Plus eine der drei Hintergrundfarben - grau, hellblau, hellgrün.

Schreiben Sie die folgenden Werte, um die Palette in den Spalten 125 und 126 festzulegen:

 x=125 x=126 palette --------------------------------------------------------------------- 00 00 COLOR: rgb, light green bg 00 ff COLOR: rgb, light blue bg ff 00 COLOR: rgb, gray bg ff ff B/W: www, black bg 

In typischen Spielen tun sie dies normalerweise: Zuerst legen sie einen bestimmten allgemeinen Hintergrund fest, für den Sie das vorgefertigte BIOS-Verfahren verwenden können:
  li $c6 ; $21 - b/w palette, fill with black. $c6 - color palette, fill with gray lr 3, A pi clrscrn ; clrscrn BIOS call 

Erstellen Sie dann bei Bedarf einen Streifen mit einer Schwarzweißpalette (um beispielsweise die Spielpunktzahl mit weißen Zahlen auf einem schwarzen Hintergrund anzuzeigen).


Und dann setzen sie Pixel in eine von drei Farben (wenn der Hintergrund grau ist - r, g, b). Infolgedessen gibt es natürlich 8 Farben, aber an einer bestimmten Stelle einen Punkt einer beliebigen Farbe zu platzieren ist so einfach - es ist unmöglich. Hier finden Sie eine Reihe von Bildern , die einen Eindruck von den Farben und ihren Kombinationen vermitteln.

Tatsächlich enden alle Grafiken als solche - alles, was Sie tun möchten, wird durch Zeichnen von Pixeln und manuell erledigt. Aus nützlichen Routinen hat das BIOS eine Zeichenausgabe. Aus Platzgründen gibt es im ROM jedoch nur Bilder von Zahlen und einzelnen Zeichen mit einer Größe von 5 x 8 Pixel:


Das Verfahren für ihre Rücknahme ist jedoch nützlich und kann wie folgt angewendet werden:

  li 25 ; column lr 1,a li 25 ; row lr 2,a li %11000000 ; eg $c0 - green "0" lr 0,a ; a -> r0 pi drawchar ; call subroutine 

In der obigen Version bestimmen die oberen beiden Ziffern im Register r0 die Farbe (10 - rot, 11 - grün, 01 - blau, 00 - transparent), der Rest - die Seriennummer des Zeichens (0 1 2 3 4 5 6 7 8 9 G? T SPACE MX BLOCK: - Mitte || links || `), beginnend bei Null. Die Register r1 und r2 sind jeweils eine Spalte und eine Zeile.

Eine praktischere Option ist, nicht über Bits nachzudenken:

  li 20 ; x lr 1,a ; a -> r1 li 10 ; y lr 2,a ; a -> r2 li $40 ; char color in bits 6,7: $80 (%10000000) - red, $c0 (%11000000) - green, $40 (%01000000) - blue, $00 (%00000000) - transparent oi 1 ; index of char ( eg 3 for "3" ) lr 0,a ; combined color + char index -> r0 pi drawchar ; call subroutine 

Um ein Gefühl für die Plattform zu bekommen, habe ich ein 256-Byte-Intro für den winzigen Intro-Wettbewerb bei Chaos Constructions'2019 geschrieben . Nichts Besonderes, aber achten Sie darauf, warum dort die zeilenweise Palettenänderung verwendet wird. Ein kriechender horizontaler Streifen hebt sozusagen die darunter liegende Linie hervor und ersetzt vorübergehend den gesamten Hintergrund durch Schwarz und alle Pixel durch Weiß. Da Sie die Pixel selbst nicht überschreiben müssen (und später nicht wiederherstellen müssen), können Sie eine solche „Hintergrundbeleuchtung“ sehr schnell und ohne Flimmern erstellen.

Der zweite Punkt sind die Buchstaben "CC". Da sich die Buchstaben "C" nicht im BIOS befinden, wird die Überlappung der Buchstaben GG und der Nummer 1 verwendet, um das inverse "CC" zu erhalten.



Ton


Der Ton ist schlecht. Offiziell gibt es drei Sounds - 120Hz, 500Hz und 1 KHz. In der Tat ist es problematisch, etwas anderes als Klicks und ein ersticktes Quietschen zu bekommen. Darüber hinaus heißt es, dass zwischen PAL- und NTSC-Maschinen sowie zwischen alten und neuen Versionen der Klang ebenfalls unterschiedlich ist. Für typische Spiele ist dies jedoch ausreichend. Ton über die Ports ein- und ausschalten:

  li %01000000 ; 1khz beep $40 outs 5 li %10000000 ; 500hz beep $80 outs 5 li %11000000 ; 120hz beep $c0 outs 5 ; some pause clr outs 5 ; turn off sound 

Die Leute hatten sogar Spaß daran, Musik zu spielen. Die besten Samples ähneln aus der Ferne dem PC-Lautsprecher. Es stimmt, es gibt sowieso keinen praktischen Sinn - alle Prozessorressourcen werden für Musik verwendet, es kann nichts Besonderes getan werden.

Entwicklungswerkzeuge


Derzeit gibt es eine vorgefertigte Auswahl der erforderlichen Software namens „Development Pack“.

Dies beinhaltet DASM Assembler, Disassembler, MESS Emulator (mit Debugger). All dies funktioniert zumindest unter Windows 7 problemlos.


Parameter für Montage und Start:

 dasm.exe test.asm -f3 -otest.bin messd channelf -cartridge %cartPath%\test.bin -w -effect sharp -r 640x480 -ka 

Der Emulator ist ziemlich gut, obwohl der Debugger dort extrem seltsam ist. Ich konnte die neue Version von MAME / MESS nicht sofort konfigurieren (ich habe festgestellt, dass das Einrichten von MAME für eine unbeliebte Plattform, die angeblich unterstützt wird, jedes Mal keine triviale Aufgabe ist).

Der Emulator nimmt an, dass die Auflösung des sichtbaren Bereichs minx = 5, minY = 5, maxX = 105, maxY = 61 entspricht

Da es kein Vergnügen ist, etwas unter den Emulator zu schreiben, ohne das Ergebnis live getestet zu haben, musste ich das Problem mit dem ROM-Emulator lösen. Auf meine Bitte hin stellte tnt23 eine spezielle Patrone her (Alexander Novozhilov druckte eine Hülle dafür), in die das EEPROM 28C16A eingesetzt wird. Aufgrund der Besonderheiten der F8-Adressierung musste ich immer noch einen alten Fairchild 3853-Chip bei eBay kaufen. Infolgedessen konnte das EEPROM so programmiert werden, dass es auf einem Live-Computer aussieht.


Zusätzlich hat tnt23 einen Kanal F S-Video-Ausgang angeschlossen (normalerweise kann er nur über den Antenneneingang an ein Fernsehgerät angeschlossen werden), wodurch die Bildqualität und die Farbwiedergabe erheblich verbessert werden.

Geschichte über Fairchild Channel F:



Ressourcen


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


All Articles