Quick-Tips

"BGI spielt falsch“ die zweite...

Dem einen oder anderen, der versucht, mit Pure C aut dem Atari und Turbo C++ unter DOS portable Programme unter Verwendung des BGI zu schreiben, werden schon manche Ungereimtheiten aufgefallen sein. Hier eine weitere Zusammenfassung meiner schlechten Erfahrungen mit Pure C:

Die Funktion setfillstyle setzt bei Pure C bei einem Aufruf der Art

setfillstyle(SOLID_FILL, 0)

keine schwarze, sondern eine weiße Füllfarbe, wie bei einem nachfolgenden Aufruf von bar leicht festgestellt werden kann. Bei Turbo C++ wird hingegen - wie bei setcolor - eine schwarze Füllfarbe gesetzt.

Die Funktion putpixel (siehe Listing) hält sich auch dann an das über setviewport angegebene Fenster, wenn das Clipping-Flag beim Aufruf von setviewport ausgeschaltet war. Außerdem setzt auch putpixel falsche Farben, wenn es im Farbmodus (z. B. mittlere TT-Auflösung) betrieben wird. Vorläufige Abhilfe schafft bei diesem Farbfehler das abgedruckte Programm.

Vorsicht bei Verwendung der Farbe mit der Nummer 15! Viele BGI-Funktionen, so u.a. setcolor, übersetzen diese dem VDI als Farbe 16. Diese Farbe existiert aber beim VDI nicht! Zwar habe ich deshalb noch keinen Programmabsturz beobachten können, zweifelhaft ist das Verfahren aber allemal.

Schließlich noch einmal - für alle, die die Ausgabe 1/92 der ST-Computer nicht zur Hand haben - der Fehler bei clear-viewport: Diese Funktion wartet ab und zu auf einen Tastendruck, was an einem - überflüssigen - Aufruf der VDI-Funktion vsm_locator am Ende der Funktion liegt. Man kann den Aufruf durch einen von vq_mouse ersetzen, wozu bei dem unten angegebenen Offset in PCBGILIB.LIB das Symbol vsm_loca durch vq_mouse mit einem Dateimonitor ersetzt werden muß:

PC Version Offset (hexadezimal)
16. Aug. 1991 $2F17
29. Aug. 1991 $2F29
20. Sep. 1991 $2F29

Ich hoffe, daß dies alle BGI-Fehler sind. Pure Software sollte sie möglichst bald beheben.

R. Lause, Bendorf

/* Vorläufiges Beheben des Farbfehlers von */
/* putpixel                                */
/* Autor: Rüdiger Lause                    */
/*                                         */
/* (c)1992 by MAXON-Computer               */
/*                                         */

#ifdef __PUREC__
#include <ext.h> /* für getch */
#else
#include <conio.h> /* für getch */
#endif
#include <graphics.h> 

int
    gdriver, /* BGI-Treiber */
    gmode, /* BGI-Mode */
    maxc; /* Größte Farbnummer */

#ifdef TOS___
/* coltrans bildet die Übersetzungstabeile. */
/* Sie ist global, damit sie nicht bei je- */
/* dem putpixel-Aufruf initialisiert werden */
/* muß. */

const int coltrans[16] = {
    0, 2, 3, 4, 5, 6, 7, 8,
    9, 10, 11, 12, 13, 14, 15, 1
};
/* Hier die Funktion _putpixel, die die */
/* Farbübersetzung richtigstellt. */
void putpixel(int x, int y, int pixelcolor)
{
    if(maxc > 1)
        putpixel(x, y, coltrans[pixelcolor]);
    else
        putpixel(x, y, pixelcolor);
}

/* putpixel wird für alle putpixel aufgerufen */ 
#define putpixel(x,y,c) putpixel(x,y,c)
#endif

/* Ein kleines Beispielprogramm */ 
int main(void)
{
    int
        step, 
        x, y, 
        i,
        col, 
        flag;

    /* Initialisierung */ 
    initgraph(&gdriver, fcgmode, "");
    /* Obligatorisch, da von putpixel */
    /* benötigt: */
    maxc = getmaxcolor();

    /* Hier das eigentliche Programm */ 
    step = (getmaxx()+1) / (getmaxcolor()+1);
    for(flag=0; flag<2; flag++) { 
        cleardevice(); 
        setviewport(step>>1, 50, getmaxx()-(step>>1)+1, getmaxy()-49, flag);
        if(step >= 2) {
            col = 0; 
            x = -(step>>1);
            while(col <= getmaxcolor()) (
                for(y=-50; y<((getmaxy()-99)>>1); y++)
                    for(i=x; i<x+step; i++) 
                        putpixel(i, y, col); 
                setfillstyle(SOLID_FILL, col); 
                bar(x, y, i-1, getmaxy()); 
                setcolor(col);
                line(x, -50, i-1, getmaxy() ) ;
                x + = step;
                col++;
           }
        }
        /* Escape bricht ab! */
        if(getch()=='\33') 
            break;
    }
    /* Grafikende */ 
    closegraph();
    /* Tschüß */ 
    return 0;
}

GFA-Compiler ohne LINEA

Das Grafiksystem der ATARI Computer beruht bei älteren TOS-Versionen auf den sogenannten LINEA-Codes. Hierbei werden bestimmte Befehlscodes, die die CPU eigentlich gar nicht kennt und die daher zu einem Fehler führen würden, abgefangen und statt dessen verschiedene Routinen zur Grafikausgabe an gesprungen. Der Trend geht aber eindeutig weg von den LINEA-Befehlen. Saubere Grafikausgabe per VDI ist gefragt. Leider verwendet GFA-Basic direkt LINEA-Befehle. Sowohl im Interpreter als auch im Compiler sind sie zu finden. Dies kann unter Umständen zu Problemen bei der Grafikausgabe führen. Wie man die unbeliebten LINEA-Befehle aus dem Compiler her-auspatcht, soll im Folgenden gezeigt werden. Man kann dazu einen beliebigen Diskettenmonitor benutzen:

Patches:

ASM-Mnemonic = Hex
nop $4E71
rts $4E75

(1) Datei-Offset: $486C

$A000, LA-INIT im Initialisierungsteil Compiler
GFA merkt sich hier A0 und A1.
A0: LA-Variablen A1: Zeiger auf Tabelle mit Zeigern auf Systemzeichensätze
Patch: nop
VORSICHT: Es werden nach $A000 die aktuellen Inhalte von AO/A1 gerettet, nach dem Patch die Werte nach einem M-SHRINK-Aufruf. Es könnten also beliebige Werte darin stehen, auch Null oder Eins. Dies würde bei manchen GFA-Befehlen dazu führen, daß bei Zugriff auf negative LA-Variablen ein Bus- oder Adreß-Error ausgelöst werden könnte. Deshalb sollte man überhaupt keine Befehle mehr verwenden, die irgendwie nur auf LA-Variablen zugreifen, also z.B. auch kein SETMOUSE.

(2) Datei-Offset: $6C82

$A00A, Hidemouse, u.a. intern vor VDI Befehlen
Patch: nop
BESSER: da kein Zugriff auf LA-Variablen Offset $6C6E, direkt am Anfang Hidemouse
Patch: rts

(3) Datei-Offset: $6CB6

$A009, Showmouse, u.a. intern vor AES-Befehlen
Patch: nop
BESSER: da kein Zugriff auf LA-Variablen Offset $6C94, direkt am Anfang Showmouse
Patch: rts

(4) Datei-Offset: $A584, $A58A

Bei Verwendung von VDI-Befehlen macht GFA im Initialisierungsteil ein vs_clip 'Clipping ein' mit der Bildschirmbreite/-höhe. Beide Werte holt es sich aus Offset -4/-12 der LA-Variablen.

Patches: jeweils $6002 (bra.s relativ zwei Byte weiter). WICHTIG: !! CLIP OFF am Programmanfang

(5) Datei-Offset: $D55E

$A00A, vor einem SupExec, Bedeutung unbekannt.
Patch: nop

Ohne Gewähr auf Vollständigkeit!

Im Interpreter $A009/$A00A Show/Hide Mouse rauspatchen! Das gibt zwar leichte „Flecken“ beim Bewegen der Maus im Interpreter, aber dafür keine beim laufenden Programm!

Auf eine saubere Schachtelung von hidems/showms (über GRAF_MOUSE AES 78) achten! Zu jedem Hide ein Show, sonst gibt’s „Flecken“. Maus nicht anschalten, wenn sie schon an ist, wie in der Regel nach dem Start von GEM-Programmen, sonst „Flecken“.

Folgende Befehle meiden: CRSCOL CRSLIN INPUT MOUSE MOUSEK MOUSEX MOUSEY SETMOUSE SHOWM HIDEM SPRITE ACHAR ACLIP ALINE APOLY ARECT ATEXT BITBLT HLINE L~A PSET PTST

...und gegebenenfalls entsprechende VDI/AES-Befehle nutzen! Von BITBLT gibt es eine VDI und eine LA-Variante!

Chr. Conrad, Aachen

' (c)1992 by MAXON-Computer
' Autor: Christoph Conrad
' Das Programm durchsucht die GFA-Library 
' nach LINEA-Codes und erzeugt eine Liste 
' mit den Offsets derselben.
'
DATA Init, Put Pixel, Get Pixel,
DATA Line, Horizontal Line 
DATA Filled Rectangle
DATA Filled Polygon, BitBlt, TextBlt 
DATA Show Mouse, Hide Mouse,
DATA Transform Mouse, Undraw Sprite 
DATA Draw Sprite, Copy raster form 
DATA Seedfill 
DIM la.name$(15)
FOR i&=0 TO 15
    READ la.name$(i&)
NEXT i&
'
lib$="GFA3BLIB"
OPEN "i",#1,lib$ 
len%=LOF(#1)
CLOSE #1 
DIM p|(len%) 
ram%=V:p|(0)
BLOAD lib$,ram%
'
OPEN "o",#1,"LINEAADR.DAT"
PRINT #1, "Offsets zum Dateistart (hex)"
'
FOR off%=0 TO len%-1 STEP 2 
    w%=CARD{ram%+off%)
    IF &HA000<=w% AND w%<=&HA00F
        info$=HEX$(off%,6)+" : "+HEX$(4)+la.name$(w% AND &HF)
        PRINT info$
        PRINT #1;info$
    ENDIF 
NEXT off%

CLOSE #1


Aus: ST-Computer 09 / 1992, Seite 149

Links

Copyright-Bestimmungen: siehe Über diese Seite