Zeichensätze vergrößern

Bei der Entwicklung von GEM hat man viele Möglichkeiten der Gestaltung geschaffen, auch eher überflüssige. Andererseits aber hat man sich bei einigen Funktionen mit mittelmäßigen Ergebnissen zufriedengegeben:

Eine maximale Textgröße von 26 Bildpunkten mag zwar bei niedriger Auflösung recht eindrucksvoll sein, reicht aber bei hoher Auflösung keineswegs zur wirkungsvollen Anwendung.

Meine Ansicht war es, eine Funktion in "C" zu programmieren, die diese "Not” ändert. Ernsthafte Programmierer werden das für eine überflüssige Spielerei halten, ich möchte aber doch behaupten, daß es auch dafür ernsthafte Anwendungen gibt!

Zuerst brauchte ich die Adresse der Systemfonts. Hier kam mir der Line-A-Befehl mit dem Opcode “0xa000” gelegen. Er liefert im Register A1 die Adresse einer Tabelle mit den Adressen der drei Systemfonts (6x6, 8x8 und 8x16). Daß er nur im Assemblercode erreichbar ist, stellt bei MEGAMAX kein Problem dar (siehe Funktion ‘fontad()’).

An der erhaltenen Adresse befindet sich im Betriebssystem jeweils ein Datenblock im VDI-Fontformat. Es wäre also elegant gewesen, ein ‘struct’ zu definieren und die einzelnen Komponenten so anzusprechen.

Da dies den Aufwand aber unnötig erhöht hätte, und die Funktion ja immerhin in einer ‘Library’ untergebracht werden, also kurz sein, sollte, entschloß ich mich, die Werte über Adreßdistanzen zu bekommen.

Distanz von 76: Zeiger auf die Fontdaten
82: Anzahl der Scanlinien = Höhe der Zeichen-”Zelle”

Jetzt galt es, die verfügbaren Informationen in entsprechender Vergrößerung auf en Bildschirm zu kopieren. Dazu besorge ich mir ein Byte der Fontdaten als Muster und übertrage jedes Bit je nach Vergrößerung mehrmals auf ein Byte des (physischen) Bildschirmspeichers, siehe Bild auf der nächsten Seite.

Diese Arbeit übernimmt die Funktion

‘bchar()’ (“b” für big). Auf diesem Weg sind theoretisch Vergrößerungen von 1 bis unendlich möglich, sinnvoll jedoch nur bis etwa 25. Die Funktion erwartet als Parameter:

  1. den auszugebenden Buchstaben
  2. die x-Koordinate
  3. die y-Koordinate
  4. ein “Modusbyte”, das die Vergrößerung und die Art der Ausgabe wie folgt enthält:

Bit 0 - Bit 4: Vergrößerung (1-31)
Bit 5: gesetzt -> transparent, nicht gesetzt -> überschreibend
Bit 6: gesetzt -> 8x8-Font, nicht gesetzt -> 8x16-Font
Bit 7: gesetzt -> invers, nicht gesetzt -> normal

Durch diese Aufschlüsselung ergibt sich folgende Möglichkeit der Definition von ‘mode’:

Bsp.:

13 13-fach vergrößerte 8x16- Fonts
13|128 wie oben, invertiert
13|64 wie oben, nur 8x8-Fonts
7|128|64 7-fach vergrößerte, inverse 8x8-Fonts

Um die Verwendung der Funktion zu erleichtern, gibt diese die Zeichenbreite zurück und ermöglicht dadurch die Plazierung der nachfolgenden Zeichen im richtigen Abstand (siehe Funktion 'bstring’).

'bstring' übergibt ’bchar' einzeln die auszugebenden Zeichen des Strings und erhöht dabei die x-Koordinate um die Zeichenbreite. Das Modusbyte wird unverändert weitergegeben (durchgeschleift). Beide Funktionen beziehen die Koordinatenwerte auf die linke obere Ecke der Ausgabe, die x-Koordinate wird auf die linke Bytegrenze abgerundet. Die Ausgabe erfolgt bei starken Vergrößerungen nicht gerade schnell, dieser Mangel wäre aber nur durch vollständige Programmierung in Maschinensprache zu beseitigen gewesen.

Durch Einführen eines zusätzlichen Parameters ist es möglich, die Textproportion, also das Verhältnis zwischen horizontaler und vertikaler Ausdehnung, für jede Ausgabe festzulegen, wodurch sich zum Beispiel Fettdruck sehr einfach realisieren ließe. Dazu müßte dieser Parameter der Variablen ‘scari anstatt von ‘size’ zugewiesen werden (oder auch:

for (scan = 0; Scan < size / 2; scan++ )’

wodurch der Text zwar mit doppelter Breite, aber nur mit einfacher Höhe ausgegeben würde).

Ein Vorteil dieser Funktionen ist, daß sie auch unter TOS verwendbar sind. Die Funktion fontad()’ läßt sich bei den glücklichen Besitzern einer RAM-TOS-Version auch dazu verwenden, durch einfaches Einkopieren in das Betriebssystem der gesamte System-Font durch einen DEGAS-Font zu ersetzen. (Ich bin gerne dazu bereit. Interessierten einen einfachen Font-Editor sowie sehr brauchbare Fonts und das "Einkopierprogramm” für den ‘AUTO-Ordner’ zur Verfügung zu stellen.)

Für die Umsetzung in Programmiersprachen, die keine Möglichkeit des Verwendung von Line-A-Befehlen besitzen, sei angemerkt, daß die benötigten Fontadressen auch an folgenden Systemadressen zu finden sind (ST-Computer 2/88. Seite 42, Rainer KRACHT):

Pointer für Font-Daten der 8x16-Font:
bei 0x607e 8x8-Font:
bei 0x41a8

Damit ergibt sich folgende Programmiermöglichkeit (Routine ‘bchar()’:

Pointerinitialisierung:

/* Die Initialisierung von fnt fällt weg; für ‘font’: */
if(mode&64)font =*(char**) 0x41a8+c; 
else font=	*(char**)	0x607e+c;

Schleifenbedingung:

/* statt: *(int*)(fnt+82) */ 
/* für 8x16:16 */ 
/* für 8x8: 8*/
extern long gemdos(), bios(), xbios();

#define	Tgettime()		(int)gemdos(0x2c)
#define	Cursconf(a,b)	xbios(21,a,b)
#define	Setcolor(a,b)	xbios(7,a,b)
#define	Kbshift(a)		bios(11,a)

#define	INVERS	128
#define	FNT2	64
#define	ODER	32

long fontad(index) 
int index;
{	register long *adr;
	asm {	move.1	A2,-(A7)
			dc.w	0xa000
			movea.1 A1, adr 
			move.1	(A7)+,A2
		}
	return *(adr + index);
}

int bchar(c, x_ko, y__ko, mode) 
int c, x__ko, y_ko, mode;
{	int y, inv = mode & 128;
	register int x, size =mode&31, scan, op=mode&32;
	register char *screen, *font, *control; 
	char work, transfer = 0, *fnt; 
	extern long xbios(); 
	long fontad();
	screen =(char *)(xbios(3)+y_ko*80+(x_ko >> 3));
	control = (char *)(xbios(3) + 32000 - size * 80) ;
	fnt = (char *)fontad(2 - ((mode >> 6) & 1));
	font = *(char **)(fnt + 76) + c;
	for (y = 0; y < *(int *)(fnt + 82); y++)
	{	work = inv ? ~*font : *font; 
		for (x = 0; x < size * 8; x++)
		{	if ((work >> (7 - (x / size))) & 1) 
				transfer |= (128 >> (x % 8)); 
			if (x % 8 == 7 && screen < control)
			{	for (scan = 0; scan < size; scan++) 
					if (op) *(screen+scan*80) |=transfer; 
					else * (screen + scan * 80) =transfer;
					transfer = 0; 
					screen++;
			}
		}
		font += 256;
		screen += (size * 79);
	}
	return size * 8;
}

bstring(string, x, y, mode) 
char *string; 
int x, y, mode;
{	while (*string) x += bchar(*string++, x, y, mode);
}

main()
{	char zeile[6]; 
	int zeit, i;
	Cursconf(0, 71); 
	atari();
	for (i = 0; i < 16; i++)
		Setcolor(i,(unsigned)(-Setcolor(i,-1) &0x777)) ;
	bstring("Beenden durch [Control]!", 224, 391,1| FNT2);
	while (!Kbshift(-1))
	{	zeit = Tgettime();
		sprintf(zeile, "%02d:%02d",
					(zeit >> 11) &0x1f, 
					(zeit >> 5)	0x3f);
		bstring(zeile, 0, 70, 16);
	}
	for (i = 0; i < 16; i++)
		Setcolor(i, (unsigned) (-Setcolor(i,-1) & 0x777));
	Cursconf(1, 71);
}

atari ()
{	int i;
	long wait;
	for (i = 1; i < 11; i++)
	{	bstring("\16\17 Atari", 320 - i * 32, 200 - i * 8,i|INVERS); 
		for (wait = 500000; wait--;);
	}
	bstring("	", 0, 120, 10);
}

Listing zum Vergrößern des Zeichenmsatzes


Franz Melchior
Aus: ST-Computer 12 / 1988, Seite 97

Links

Copyright-Bestimmungen: siehe Über diese Seite