... und dazu etwas SoftwareArnulf SoppWie nützlich ein Umbau am Computer ist, zeigt sich natürlich erst, wenn er etwas zu tun bekommt. Das folgende Programm ist nur ein Beispiel, was man mit dem Versechzehnfacher anfangen kann. Jedes andere Maschinenprogramm, sogar BASIC-, Pascal- oder sonstige höhere Programmtexte können dort untergebracht werden (1,2), natürlich auch Datenbytes für Tabellen und dergleichen. Damit ist das leidige Himem-Thema von Tisch; nahezu jede popelige BASIC-Verschönerung (eingerückte Zeilennummern und ähnlich überflüssiges) drängelt sich dort oben und verschleißt den Platz für wirklich Wichtiges. Dieses Programm ist ein Treiber für die HRG 1b von RB-Elektronik. Er lädt selbsttätig BASIC/CMD und arbeitet anschließend im Hintergrund mit BASIC zusammen. Sein Ladebereich geht von 3000-32E4. Dahinter sind noch ein paar Bytes als Datenpuffer reserviert. Um beim Laden des Treibers nicht den DOS-Fehler "Ladeversuch auf ROM-Speicherplatz" serviert zu bekommen, muß dort natürlich RAM vorhanden sein. Der User gibt deshalb zuvor auf den Port F0 die Nummer eines Steckplatzes auf dem Versechzehnfacher aus, wo ein statisches RAM sitzt. Unter H-DOS geht das mit OUT F0,xx (7). Ansonsten kann man zunächst BASIC starten und dann OUT 240,xx anschließend CMD"S=HRG" eingeben (sofern man dieses Programm unter dem Namen HRG/CMD auf Disk stehen hat). A propos H-DOS: Da der Befehl CMD > (mehr darüber weiter unten) das Parallel-RAM auf der CPU-Platine benutzt, müssen Besitzer des EG 64 MBA mit diesem DOS zuvor INI.N eingeben. Damit werden zwar die interessantesten Features von H-DOS disabled, aber noch immer hat der User alle G-DOS-Möglichkeiten und noch ein bißchen mehr. Auf allen Maschinen, mit denen Banking nicht möglich ist, funktioniert dieser Befehl ganz einfach nicht, ohne aber Schaden anzurichten oder zu einem Fehler zu führen. Der Treiber stellt eine Reihe von Kommandos an die HRG zur Verfügung. Sie alle beginnen mit CMD (1). Um dem Interpreter anzuzeigen, daß es sich nicht um das gewohnte CMD handelt, folgt unmittelbar darauf nicht eine Variable oder ein Ausdruck zwischen Gänsefüßchen, sondern ein zweites BASIC-Token: CMD + : HRG einschalten CMD - : HRG ausschalten CMD CLS : HRG-Speicher löschen CMD SET : einen HRG-Punkt setzen CMD RESET : einen HRG-Punkt löschen CMD POINT : testen, ob ein HRG-Punkt gesetzt ist CMD < : HRG invertieren (weiß <-> schwarz) CMD LPRINT : HRG-Inhalt auf Drucker ausgeben (Hardcopy) CMD ASC : ASCII-Bildschirm in Hex anzeigen, bis neue Taste gedrückt CMD > : Bildschirm gegen Pufferinhalt austauschen CMD LINE : noch nicht programmiert, ergibt aber keinen Fehler Nach der üblichen BASIC-Syntax können CMD und das zweite Token direkt oder durch Blank getrennt hintereinander stehen. Diese Befehle können im Direktmodus und als Bestandteil eines Programms eingegeben werden. Die drei erstgenannten HRG-Befehle bedürfen keiner näheren Erläuterung. CMD SET, CMD RESET und CMD POINT haben eine ganz ähnliche Syntax wie die gewohnten Befehle zur Ansteuerung der Genie-Pixelgraphik. Im Argument sind im Unterschied dazu jedoch Koordinaten im Bereich 0-383 für X und 0-191 für Y zulässig, entsprechend der feineren HRG-Matrix. Die Koordinaten können wie in Level 2 oder Disk-BASIC auch durch Variable dargestellt werden. CMD < macht aus jedem Punkt im HRG-Speicher sein Komplement. Gesetzte Punkte werden dunkel, nicht gesetzte werden eingeschaltet. Es entsteht eine negative Darstellung. Der normale ASCII-Bildschirm bleibt hiervon unberührt. Bei einem Bildschirmausdruck der HRG mit CMD LPRINT wird der Drucker zunächst in den Einschaltzustand versetzt (Reset aller Druckparameter). Danach wird der linke Rand auf die 9. Stelle gesetzt, um das Bild zu zentrieren. Der Zeilenabstand wird mit 6/72" so eingestellt, daß die Druckzeilen lückenlos untereinander stehen. Nach getaner Arbeit werden diese Steuercodes alle wieder gelöscht; der Drucker ist wieder im Einschaltzustand. Diese Codes gelten für den Star Gemini-10X. Für andere Printer müssen sie entsprechend geändert werden. Von den vergleichbaren Epson-Typen ist mir bekannt, daß für die Randeinstellung lediglich in ESC M 09 aus dem "M" ein "1" gemacht zu werden braucht. Die übrigen Codes sind identisch. Der Befehl CMD ASC ist für vielerlei Verwendungen interessant. Mit ihm hat der Programmierer sozusagen immer eine ASCII-Tabelle auf dem Bildschirm. Die ASCII-Zeichen werden als zweistellige Hexzahlen dargestellt (4). So werden gleiche Zeichen mit verschiedenen Codes unterscheidbar, um nur eine Anwendung zu nennen: Die beiden Blanks mit den Codes 32 und 128 sowie die Graphikblocks 128-191 und 192-255 sind als Hexzahlen eindeutig zu identifizieren. Bei der Ausführung von CMD ASC werden die 32er Blanks übrigens nicht mit umgewandelt, sondern als Leerzeichen belassen, um den Bildschirm übersichtlich zu halten. Dabei wird der normale ASCII-Bildschirm natürlich gelöscht, sonst würde er stören. Der Treiber rettet ihn in den HRG-Speicher, so daß -er nach dem Druck auf irgendeine Taste wieder restauriert werden kann. Ein besonderer Puffer im RAM ist dafür nicht erforderlich. Nach diesem Schema geht auch der Befehl CMD > vor. Zunächst wird der Bildschirm in die HRG gerettet. Von ihr sind nämlich nur 6 Bits pro Byte sichtbar, die beiden höchstwertigen Bits sind unbenutzt und können den Bildschirm aufnehmen. Dabei wird der sichtbare Inhalt des HRG-Speichers nicht beeinträchtigt. Alle Graphiken bleiben also erhalten. Im weiteren Verlauf der Ausführung dieses Befehls wird nun der Inhalt der HRG, also Graphik und ASCII, in einen Puffer gerettet, und der Inhalt dieses Puffers geht dafür in die HRG. Die beiden höchstwertigen Bits des neuen HRG-Inhalts werden in den ASCII-Bildschirm übertragen. Es ist demnach ein Austausch Bildschirm gegen Puffer. In diesem Treiber liegt der Puffer im Adreßbereich ab 0000. Das ist natürlich nur mit dem EG 64 MBA oder einem anderen Banker realisierbar. Entsprechende Änderungen, um stattdessen das gute alte Himem dafür zu benutzen, sind kein Problem. Der Befehl CMD LINE soll eines fernen Tages, wenn der Autor mal wieder Lust hat, an dem Treiber weiterzuarbeiten, Linien, Rechtecke usw. ziehen. Der Leser möge mir nachsehen, daß die Computerei mein Hobby ist, bei dem ich gnadenlos dem Lustprinzip folge (6). An diesem fernen Tage werden wohl noch ein paar andere Modifikationen folgen, die es ermöglichen. den HRG-Treiber fest in ein EPROM zu brennen. Das ist mit dieser Version nicht möglich, denn das Programm vollzieht Schreibzugriffe in seinem eigenen Adreßraum. Dazu gehören z. B. die Datenpuffer an seinem Ende, aber auch variable Sprungdistanzen mitten im Programm (Selbstmodifikation). Der Vorteil dieser Variante ist freilich, daß der Treiber mit den Bedürfnissen jederzeit mitwachsen kann. Immerhin sind noch eineinviertel kB frei! Auf die Programmlogik möchte ich an dieser Stelle nicht eingehen. Die siebeneinhalb Seiten Listing wären halbwegs erschöpfend wohl nicht mit weniger als 15 Seiten Test erklärbar. Insbesondere diejenigen Features, die kein anderer mir bekannter HRG-Treiber zur Verfügung stellt, würden einige Seiten füllen: Z. B. die Umwandlung des ASCII-Bildschirms in die Hexdarstellung und das Puffern desselben im HRG-Speicher. Der Maschinensprache-Freak mag sich dabei amüsieren, sich in dem sehr ausführlich kommentierten Listing selber zurechtzufinden. Zu diesem Thema sind an gleicher Stelle auch bereits ein paar Beiträge erschienen, die die Arbeit deutlich erleichtern werden (5 u.a.). Nur einige wenige Kommentare, ohne die sich sogar der Autor kaum noch im Programm zurechtfindet, sollen angefügt sein: In BASIC/CMD steht nach dem Laden (also noch vor dem Ansprung!) an 67DD der CMD-Vektor (JP 57FF). Er wird durch JP cmd (3074) ersetzt. Andere Treiber benutzen kein bereits vorhandenes Token und verlangsamen damit den ganzen Computer: es muß bei jeder Eingabe geprüft werden, ob ein vorangestelltes Doppelkreuz o. dergl. ein Syntaxfehler oder die Einleitung eines HRG-Befehls ist. An der Stelle 64F3 wird HL als Zeiger auf das BASIC-Helle geladen. Mit der Änderung des LSB von 5C auf 5E werden die beiden ersten Codes, die den Bildschirm löschen, übergangen. So bleibt die oberste Titelzeile erhalten, die beim Label hello steht. Beim späteren Programmablauf wird der Treiber nur dann angesprungen, wenn das CMD-Token angetroffen wurde. Nun prüft er, was folgt. In Disk-BASIC ist es immer ein Anführungszeichen oder ein Variablenname. Diese Zeichen liegen im Bereich bis 7F. Der Vergleich mit 80 beim Label cmd gibt deshalb Aufschluß, ob zur Ansteuerung der HRG ein weiteres Token folgt. Falls nein, geht es in der alten CMD-Routine weiter, falls ja, kommt der Treiber jetzt so richtig in Fahrt. Anwender, die mit EDTASM/CMD oder ASM/CMD arbeiten. müssen auf die für diese Assembler zulässige Syntax achten; Labels dürfen höchstens 6 Zeichen lang sein, Kleinbuchstaben sind nur in den Kommentaren erlaubt, DB, DW und DM müssen als DEFB, DEFW und DEFM ausgeschrieben werden. Bei diesen Statements dürfen auch nicht mehrere Argumente in derselben Zeile stehen, schon gar nicht DEFM und DEFB gemischt. Je eine eigene Zeile muß dafür eingerichtet werden. Dieser HRG-Treiber ist, wie gesagt, lediglich eine Demonstration dafür, was mit Helmut Bernhardts Versechzehnfacher so alles anzufangen ist. Die Platine funktioniert selbstverständlich ohne HRG, auch ohne DOS ebenso gut wie mit. Vielleicht fällt einem von euch für eins der nächsten Infos eine sinnvolle Verwendung für Level 2 ein? Literatur: 1) "PUT TO - ein neuer BASIC-Befehl", 4/1984 2) "Bank Selection mit dem Genie I", 5/1985 3) "Neuer DOS-Befehl: OUT port#,xx,yy,...", 11/1984 4) "VIDHEX - Hexanzeige des Bildschirms mit der HRG", 9/1985 5) "Die HRG 1b programmieren", 11/1984 (alle von A. Sopp im Club-Info des Genie/TRS80-User-Club Bremerhaven, Ausgabe jeweils angegeben). 6) R. Goscinny, M. Uderzo: "Asterix und der Kupferkessel", Dargaud S. A. 1969 00001 ; 00002 ; 00003 ; BASIC-Treiber für die HRG 1b von RB-Elektronik 00004 ; 00005 ; Demo-Programm zum Speicher-Versechzehnfacher 00006 ; im Adreßraum 3000-370F von Helmut Bernhardt 00007 ; 00008 ; (C) Arnulf Sopp 00009 ; 00010 ; 00011 3000 00012 ORG 3000h ;im Sonder-ROM-Bereich 00013 00014 ;DOS-Eingabepuffer retten 3000 11E432 00015 finit LD DE,cmdbuf ;Puffer für Aufrufbefehl 3003 014800 00016 LD BC,0048h ;ca. Lng. DOS-Eing.-puff. 3006 E5 00017 PUSH HL ;Aufrufbefehl retten, 3007 D5 00018 PUSH DE ;weil 4419 den Puffer- 3008 C5 00019 PUSH BC ;Inhalt verändert 3009 EDB0 00020 LDIR ;zwischenspeichern 00021 00022 ;Initialisierungen in BASIC/CMD 3008 212C30 00023 LD HL,command ;BASIC-Ladekommando 300E CD1944 00024 CALL 4419h ;BASIC/CMD laden 3011 217430 00025 LD HL,cmd ;neuer CMD-Vektor 3014 22DD67 00026 LD (67ddh),HL ;in BASIC/CMD laden 3017 3E5E 00027 LD A,5eh ;LSB des BASIC-Logo 3019 32F464 00028 LD (64f4h),A ;CLS verhindern 301C 213830 00029 LD HL,hello ;HRG-Logo 301F CD6744 00030 CALL 4467h ;anzeigen 3022 C1 00031 POP BC ;Länge Eingabepuffer 3023 E1 00032 POP HL ;Aufrufbefehl 3024 D1 00033 POP DE ;Adresse Eingabepuffer 3025 D5 00034 PUSH DE ;brauchen wir gleich 3026 EDBO 00035 LDIR ;Befehl restaurieren 3028 E1 00036 POP HL ;Befehlserweit. oder CR 3029 C3BE66 00037 JP 66beh ;BASIC-Kaltstart 00038 00039 ;DOS-Befehl, um BASIC in den Speicher zu laden 302C 6C 00040 command DM 'load,basic/cmd',0dh 00041 00042 ;neue 1. Zeile des BASIC-Hello 3038 1C 00043 hello DM 1ch,1fh,'H R G 1 b - Utility von ' 3056 54 00044 DM 'The HACKTORY Arnulf Sopp für',Oah,0dh 00045 00046 ;BASIC-Erweiterung für HR-Graphikbefehle 3074 FE80 00047 cmd CP 80h ;Graphik-CMD-Befehl? 3076 DAFF57 00048 JP C,57ffh ;norm. weiter, falls nein 00049 00050 ;Es ist ein HRG-Befehl. Erkennen und ausführen: 3079 FED4 00051 CP 0d4h ;Bildschirm austauschen? 307B 2029 00052 JR NZ,CLS ;falls nein 00053 00054 ;CMD >: Bildschirm gegen Pufferinhalt austauschen 307D E5 00055 PUSH HL ;Befehlszeiger 307E CD5332 00056 CALL vidsav ;Bildschirm retten 3081 F3 00057 DI ;bloß keine Störungen! 3082 3E08 00058 LD A,8 ;RD RAM 0000-2FFF 3084 D3DF 00059 OUT (0dfh),A ;auf Banking-Port ausg. 3086 3C 00060 INC A ;WR RAM 0000-2FFF 3087 D3DF 00061 OUT (0dfh),A ;dto. 3089 65 00062 LD H,L ;HL <- 0000, Pufferadr. 308A 55 00063 LD D,L ;DE <- 00xx, HRG-Adresse 3088 50 00064 LD E,L ;DE <- 0000 308C 0E30 00065 LD C,30h ;Konst. HRG-MSB 308E CD4B32 00066 swaplop CALL HRGadr ;HRG-Stelle adressieren 3091 DB04 00067 IN A,(4) ;HRG-Byte laden 3093 46 00068 LD B,(HL) ;Pufferbyte holen 3094 77 00069 LD (HL),A ;HRG-Byte puffern 3095 78 00070 LD A.B ;Pufferbyte 3096 0305 00071 OUT (5),A ;auf HRG ausgeben 3098 23 00072 INC HL ;Pufferzeiger erhöhen 3099 7A 00073 LD A,D ;überprüfen, ob 309A 89 00074 CP C ;HkG-Bereich überschr.? 3098 38F1 00075 JR C.swaplop ;falls nein 309D DBDF 00076 IN A,(0dfh) ;Banks rücksetzen 309F FBI 00077 EI ;INTs wieder zulassen 30A0 CD5532 00078 CALL savrest ;Bildsch. restaurieren 30A3 E1 00079 POP HL ;Befehlszeiger 30A4 1831 00080 JR exit1 ;fertig 00081 00082 ;CMD CLS: HRG-Speicher löschen 30A6 FE84 00083 CLS CP 84h ;CLS? 30A8 2004 00084 JR NZ,INV ;falls nein 30AA 1E00 00085 clear LD E,0 ;Flag für HRG-CLS 30AC 1806 00086 JR clsinv ;dort weiter 00087 00088 ;CMD <: HRG invertieren (positiv -> negativ) 30AE FED6 00089 INV CP Od6h ;invertieren? 3080 2027 00090 JR NZ,LINE ;falls nein 3082 1EFF 00091 LD E,0ffh ;Flag für Inversion 3084 010330 00092 clsinv LD BC,3003h ;8 = MSB 12kB, C = Port 3 3087 C5 00093 msloop PUSH BC ;retten 30B8 05 00094 DEC ;B um 1 zu hoch 30B9 ED41 00095 OUT (C),B ;MSB HRG-Adresse 3088 0600 00096 LD B,0 ;B <- 0 für HRG-LSB 30BD 0D 00097 DEC C ;Port 2 für LSB 308E ED41 00098 lsloop OUT (C),B ;LSB HRG-Adresse 3000 DB04 00099 IN A,(4) ;HRG-Byte holen 30C2 F5 00100 PUSH AF ;retten 30C3 E6C0 00101 AND 0c0h ;obere Bits isolieren 3005 57 00102 LD D,A ;und retten 3006 F1 00103 POP AF ;HRG-Byte 3007 2F 00104 CPL ;invertieren 3008 E63F 00105 AND 3fh ;obere Bits ausmaskieren 30CA CB7B 00106 BIT 7,E ;CLS oder INV? 30CC 2001 00107 JR NZ,outa ;falls INV 30CE AF 00108 XOR A ;sonst löschen 30CF 82 00109 outa OR D ;obere Bits hinzufügen 3000 0305 00110 OUT (5),A ;Blank od. Kompl. ausgeb. 3002 10EA 00111 DJNZ lsloop ;LSB: 00, FF, FE ... 01 3004 C1 00112 POF BC ;MSB und Port für MSB 3005 10E0 00113 DJNZ msloop ;MSB-1: 2F ... 00 00114 00115 ;Rückkehr für mehrere Unterprogramme 3007 23 00116 exit1 INC HL ;Befehlszeiger nachst. 3008 C9 00117 RET ;erledigt 00118 00119 ;CMD LINE: (bisher nicht programmiert) 3009 FE9C 00120 LINE CP 9ch ;LINE? 3008 28FA 00121 JR Z,exit1 ;vorl. nicht implement. 00122 00123 ;CMD 4: HRG-Speicher in den Bildschirm einblenden 3000 FECD 00124 CP Ocdh ;HRG einschalten? 30DF 2004 00125 JR NZ,HRGoff ;falls nein 30E1 0301 00126 OUT (1),A ;einschalten 30E3 18F2 00127 JR exit1 ;fertig 00128 00129 ;CMD - HRG-Speicher aus dem Bildschirm ausblenden 30E5 FECE 00130 HRGoff CP Oceh ;HRG ausschalten? 30E7 2004 00131 JR NZ,LPRINT ;falls nein 30E9 0300 00132 OUT (0),A ;ausschalten 30EB 18EA 00133 JR exit1 ;fertig 30ED FEAF 00134 30EF 2066 00135 ;CMD LPRINT: Hardcopy des HRG-Speichers 00136 LPRINT CP 0afh ;LPRINT (Hardcopy)? 00137 JR NZ,ASC ;falls nein 00138 00139 ;LPRINT; Drucker initial.: Reset, 6/72" Zeilenabstand 30F1 E5 00140 PUSH HL ;Befehlszeiger retten 30F2 210632 00141 LD HL,prestor+1 ;Druckerinitialisierung 30F5 0609 00142 LD B,9 ;mit 9 Codes 30F7 CDFC31 00143 CALL lprint ;Ausgabe auf Drucker 00144 00145 ;HRG-Zeiger laden, 16 (Doppel-)Zeilen vorbereiten 30FA 50 00146 LD D,B ;DE <- 00xx 30FB 58 00147 LD E,B ;DE <- 0000, Start HRG 30FC 010610 00148 LD BC,1006h ;16 Zeilen, Konst. 6 00149 00150 ;1 Doppelzeile zu je 6 Dotzeilen drucken 30FF C5 00151 scrnlop PUSH BC ;Zähler retten 3100 D5 00152 PUSH DE ;dto. HRG-Zeiger 3101 0602 00153 LD B,2 ;2 Halbzeilen/Zeile 3103 C5 00154 linelop PUSH BC ;wird verändert 3104 D5 00155 PUSH DE ;dto. HRG-Zeiger 3105 21DF32 00156 LD HL,lninit ;Druckerinit. für 1 Zeile 310B 0605 00157 LD B,5 ;mit 5 Codes 310A CDFC31 00158 CALL lprint ;Ausgabe 3100 21E432 00159 LD HL,buffer ;Puffer für Druckercodes 3110 0640 00160 LD B,40h ;64 Bytes/Zeile 00161 00162 ;1 Halbzeile drucken 3112 C5 00163 hlinlop PUSH BC ;Zähler retten 3113 D5 00164 PUSH DE ;dto. HRG-Zeiger 3114 78 00165 LD A,E ;LSB des HRG-Zeigers 3115 D302 00166 OUT (2),A ;auf HRG ausgeben 3117 41 00167 LD B,C ;6 Bytes senkrecht 00168 00169 :1 Byte drucken 3118 C5 00170 bytelop PUSH BC ;wird verändert 3119 7A 00171 LD A,D ;MSB des HRG-Zeigers 311A 0303 00172 OUT (3),A ;auf HRG ausgeben 311C DB04 00173 IN A,(4) ;Dotzeile aus HRG 311E 41 00174 LD B,C ;6 Dots/Stelle 311F E5 00175 PUSH HL ;retten 00176 00177 ;6mal 1 Bit errechnen 3120 0F 00178 bitlop RRCA ;Cy <- HRG-Bit 3121 CB16 00179 RL (HL) ;nächstes Pufferbit <- Cy 3123 CBB6 00180 RES 6,(HL) ;nur untere Bits 3125 23 00181 INC HL ;nächstes Pufferbyte 3126 10F8 00182 DJNZ bitlop ;bis 6 Dots gepuffert 00183 00184 ;6 Bits fertig - 6 Bytes vervollständigen 3128 14 00185 INC D ;MSB auf nächste Dotzeile 3129 14 00186 INC D ;= um 1 kB erhöhen) 312A 14 00187 INC D 3120 14 00188 INC D 312C E1 00189 POP HL ;Pufferzeiger 312D C1 00190 POP BC ;Zähler 312E 10E8 00191 DJNZ bytelop ;bis 1 Stelle im Puffer 00192 00193 ;6 Bytes ausdrucken und weiter mit Halbzeile 3130 E5 00194 PUSH HL ;wird verändert 3131 41 00195 LD B,0 ;6 Dotspalten 3132 CDFC31 00196 CALL lprint ;ausgeben 3135 E1 00197 POP HL ;Pufferzeiger 3136 D1 00198 POP DE ;alter HRG-Zeiger |