Persze ez lehetetlen, de mégis lehet olyan látszatot kelteni, mintha a monitor szöveges módban lenne, és közben jókat grafikázni. Ehhez azonban némi elméleti háttér szükségeltetik.

A Text mode: a szöveges képernyő 80X25 karakterből áll.-mik nem derülnek ki- a legkisebb változtatható egység is egy karakter. A képernyő tartalma a b800 szegmensen van. Valahogy így: karakter, attributum, karakter, attributum ... Folytonosan mind a 2000 karakter, és a hozzá tartozó attributum. Mind a karakter, mind az attributum byte-os adat, ebből következik hogy egy teljes szöveges képernyő letárolásához 4000 byte-ra van szükség, mégis 64000 byte van fenntartva, így elvileg tudunk kezelni - ha ügyesek vagyunk- képernyőoldalakat. Valójában a képernyő 16 színű, és 720X512 pixelből áll, ezekből a pixelekből állnak a karakterek. Egy karakter (alapesetben) 9X16 pixel. Hogy honnan veszi a kártya a karakterek alakját ? El van tárolva. A VGA kártya 3 féle karakterkészletet tud. 8X8 8X14 8X16 természetesen mindegyik 256 elemű. A 9X16 nem volt elírás, úgy jön ki, hogy a keretrajzoló karaktereknél (ASCII 193-216) a karakter adott sorában a kilencedik pixel egyenlő a 8. pixellel, nem keretrajzoló karaktereknél pedig mindig háttér színű. Ennek megfelelően létezik 9X8, és 9X14 is. Ezek a készletek egy kis bűvészkedés után az A000-s szegmensen érhetők el.

Remélem elég rövid, tömör, felesleges, és érthetetlen volt. Akkor a lényeg: mint említettem, szöveges módban nem lehet grafikázni, tehát grafikus módba kel váltanunk. De milyenbe? Olyanba ahol az említett 3 karakterkészletek közül valamelyikkel kijön a 80 oszlop és a 25 sor, valamint tudunk 16 színt kezelni. Ilyen szabványos felbontás a 640X350 8X14-es karakterekkel. 

Ha azt a látszatot akarjuk kelteni, mintha szöveges módban lennénk, ugyanazokat a karaktereket kell visszaírnunk a képernyőre, ami elöttünk rajta volt. Viszont videómód váltáskor a képernyő-memória törlődik. Akkor mentsük el ! Nincs más dolgunk, mint a 0b800:0000 címtől kezdődő 4000 byte-ot átmásoljuk valami biztos helyre. Ehhez a látszólag nudli művelethez (ha elegánsak akarunk lenni) szükséges a dinamikus memóriakezelés (pointerek, stb.) és a move utasítás ismerete. Nosza:
 

{...}var savedscreen: Pointer; {ide fogunk mozgatni, ez a
lementési terület}
    screen : Pointer; {a szöveges képernyő kezdőcíme, majd
dunk értéket neki} {de meg lehetne oldani var screen: Array[1..4000] of Byte Absolute $B800:$0; módon is ! DE ekkor nem POINTER !!! }
{... ...} procedure savescreen; begin
screen:=Ptr($B800, $0); GetMem(savedscreen, 4000); {lefoglalunk 4000
byte-ot,(ennyi a képernyô)}
Move(screen^, savedscreen^ ,4000); {oszt beléje
mozgassuk a cuccot)
end;

Ez megvan, de ettől a monitoron még semmit nem fogunk látni. Először is nem ártana képernyőmódot váltani. Ahogy azt már eldöntöttük, 640x350-es módot használunk, ez pedig akár a Graph unittal is lehetséges, ami profisan - csak szerényen - így néz ki:

 
{...}
{$l egavga.obj} {megmondjuk a fordítónak, hogy ezt az obj-t is linkelje belénk}
procedure egavgadriver; EXTERNAL; {a bgi driver, amit az
obj tartalmaz}
{..., ...} procedure graph_init; var gd,gm : integer; begin
{megadjuk a graph unitnak a driver címét,} if (RegisterBGIdriver(@EGAVGADriver) < 0) then begin
{és egyben ellenôrizzük is, hogy vajon elfogadta-e} Writeln('Nem sikerült beépíteni a BGI file-t!'); Halt;
end; detectgraph(gd,gm); gm:=1; {640X350} initgraph(gd,gm,''); {váltás} if GraphResult <> grOK then {biztos, ami biztos...} begin
writeln('Nem sikerült elindítani a grafikát!'); halt;
end;
end;

Ugye még minden világos?

Nekiállunk karaktereket írogatni, de milyen színnel? Az attributum egyszerre tartalmazza a karaker előtér és háttér színét. Így:

attributum=háttérszín*16+elôtérszín

Mind a háttér, mind az előtérszín a 16 színű. Kivéve, ha a kártya 8 háttérszín+villogás üzemmódban van, de ezt most hagyjuk!

Tehát, karaktereket rajzolgatunk, már azt is tudjuk milyen színűre. Erre nem kell külön eljárást írni mert a 10h megszakításnak több funkciója is van ami épp erre való, azonban ebben a grafikus módban nekem csak ez az egy működött :

Write string:

ah 13h
al az írás módja
       00h a kurzor pozíciója nem változik meg
       01h a kurzor a szöveg végére kerül
bh az írni kívánt lap száma (grafikus módoknál 0)
bl kiírandó string színe
cx a string hossza
dh,dl x és y koordináta
es:bp mutató a stringre

De az élet nem habostorta. Honnan fogja tudni a szerencsétlen, hogy én 8x14-es karaktereket akarok? A használni kívánt karakterkészletet előbb be kell tölteni. Erre is van egy funkciója a VGA-BIOS-nak:

Graph Mode Char Functions:

    ah 11h
    al 22h: 8X16-os karakterkészlet betöltése.
    bl : 2 (25 sor)
- és még sok-sok dolog, ami számunkra lényegtelen -

Mielőtt betűket rajzolnánk, nem árt gondoskodni a háttérszínről. Legegyszerűbb úgy megoldani, hogy háttérszínű 229-es - teli téglalap - ASCII kódú karaktert írunk ki. - a módszer elég durva, de működik -

Valahogy így:
 

procedure drawtext; var x,y : byte;       p : longint; begin
asm
mov ax,1122h int 10h {8X14-es fontkészlet}
end; p:=longint(savedscreen); {a pointerbôl longintet csinálunk} for y:=0 to 24 do for x:=0 to 79 do begin
asm
jmp @go @space: {ez itt a háttérnek van} db 219 {ilyen gányolást nem szabadna csinálni, de ez van} @go: push bp {a bp-t illik elmenteni, különben fagyás} mov dh,y {átadjuk a paramétereket a BIOS rutinnak} mov dl,x les bp,p mov bl,es:[bp+1] mov bp,offset @space {Elôször a hátteret rakjuk ki} mov ax,1300h push cs pop es xor bh,bh shr bl,4 { A háttér színe a felsô négy bitben van} mov cx,1 int 10h pop bp push bp les bp,p mov bl,es:[bp+1] and bl,16 {Az elôtér színe az alsó 4 bitben van} mov al,es:[bp+1] shr al,4 {egy kis} xor bl,al {bűvészkedés a bitekkel} or bl,128 { meg lesz magyarázva} xor bh,bh mov cx,1 mov ax,1300h int 10h {karakter kirajzolása} pop bp
end; inc(p,2);
end;
end;

Szóval van egy kis bibi. Ez az rutin vagy teljesen felülírja mind a 8x14 pixelt (ezt használjuk ki a háttér kitevésénél), vagy xor kapcsolatba hozza a képernyővel, ha a karakterszín 7. bitje be van billentve (ez nálam azt jelenti, hogy 1). Mindkét esetben elcsesszük a hétteret. Ezért kell egy picit foglalkoznunk a bitekkel. Tehát világos hogy az előtérnél mi az xor-olast fogjuk kihasználni. Ha valamit kétszer ugyanazzal xor-olunk, visszakapjuk az eredeti számot. Ezért egyszer mi xor-oljuk az előtérszínt a háttérrel, egyszer meg a rutin, így épp jó szín lesz kint a monitoron. Persze útközben még a hetedik bitet bebillentjük (or bl,128).

Hát ilyen egyszerű.

Azt sem árt elintézni, hogy a kurzor a programunk előtt, és után is ugyanott legyen. (wherex, wherey)