Každý dneska šílí po grafice, okýnkách, miliónech barev a já
nevím o čem ještě. Pak se diví, že jeho Pentium to nějak nezvládá,
že se jeho prográmek cuká avůbec, že to není hezké. Vraťte se tedy
ke kráse textového režimu. Vemte si Výheň. Ta je celá v texťáku a je
přitom hezká, plynulá a bez okýnek. Prostě texťák má svoje kouzlo.
Lidi ale nemají texťák moc rádi, připadá jim strohý, jednoduchý
a stále stejný. Berou všechny jeho kvality, ale neumí jich využít.
My se teď na texťáky podíváme, takže hurá na to.
Nejprve kde ho máme. Textový mód se nám nachází ( mluvím o
VGA adaptérech ) v oblasti od B800:0000 dál. Trochu jinak je to
u Herkulů, ale pochybuji, že ho ještě někdo vlastní ( kromě Ferdy, a
ten ho má kvůli dual - monitor - systému ), ale budiž. Herkulesovi
začíná videopaměť na BC00:0000. Samozdřejmě se rozdílných počátků dá
využít právě dual monitor systémem, ale je to trochu složitější, něž
pouhý zápis. Vraťme se ale k normálnímu VGA adaptéru.
Textová videopamět tedy začíná na adrese B800:0000. Skádá se vždy
ze dvojic bytů. První byte je vždy znak a druhý byte je atribut.
V atributu je vždy uložená barva znaku, barva pozadí a blikání.
Vypadá asi takhle:
Atribut bity
7 6 5 4 3 2 1 0
| | | | +---+---+---+-- Bity barvy
+ - +---+---+------------------ Bity pozadí*
+------------------------------ Bit blikání
Se 7mým bitem je bit ve kterém je uloženo, zda bude barva blikat
či nikoliv. Je ale možné textový mód přepnout do režimu, kdy je
sedmý bit použit jako bit pozadí a potom máme namísto osmi barev
pozadí barev šestnáct. Hodnotu atributu tedy dostaneme vztahem:
Barva_znaku + Barva_pozadí * 10h ( + 80h blikání )
Přičtením oněch 80h zapneme poslední bit a znak se rozbliká nebo
pozadí bude světlé. Už víme jak vytvořit atribut. Toto je však pro
ty z vás, co ho budou tvořit sami ( assembler a pod ). Pod Pascal je
zlepšovák. Vrámci unity Crt existuje proměná Textattr, ve které je
uložen aktivní atribut. Ten se mění příkazy TextColor a
TextBackGround. Crt má samozdřejmě své konstanty, takže si nemusíte
barvy pamatovat a můžete je rovnou psát slovy. Pro ty neznalejší
z vás je tu tabulka barviček:
Tmavé barvy a barvy pozadí Světlé barvy
0 - Black - Černá 8 - DarkGray - Tmavě šedivá
1 - Blue - Modrá 9 - LightBlue - Světle modrá
2 - Green - Zelená 10 - LightGreen - Světle zelená
3 - Cyan - Vyblitá ( ta 11 - LightCyan - Světle vyblitá
vážně tak 12 - LightRed - Světle červená
vypadá ) 13 - LightMagenta - Světle růžová
4 - Red - Červená 14 - Yellow - Žlutá
5 - Magenta - Fialová 15 - White - Bílá
6 - Brown - Hnědá
7 - LighGray - Světle šedivá 128 - Blink - blikání ( přičíst )
( Omlouvám se čtenářům Výhně, ale fialovou neuvidíte, neb je
Výhní rezervovaná jako barva pro tlačítka a paleta stále dělá fade
in a out ).
Teď už víte jak nastavit barvu. A jak vypsat znak na obrazovku.
Lze to samodřejmě provést přes BIOS, ale je to pomalé a napřílad na
přepis celé obrazovky to nestačí. O módech větších než 80*25 ani
nemluvím. Co tedy zkusit zápis přímo do paměti? Známe místo, známe
barvu, nic nám nebrání. Jak jsem se zmínil, byty jsou uspořádány
výjmečně dle X a v pořadí znak, atribut, znak, atribut,... Pokud
tedy chceme zapsat znak na Xtý řádek, Ytý slopec, zapíšeme ho do
místa B800:(X+Y*šířka_obrazovky)*2. Atribut bude na následujícím
bytu, tedy na B800:(X+Y*šířka_obrazovky)*2+1. V pascalu bude
přiřazení pro mód široký Š vypadat asi takhle:
Procedure PutCharXY ( X,Y : Byte ; Ch : Char ; Color,Back : Byte) ;
Begin
Mem [B800:(X+Y*Š)*2] := Ord ( Char ) ;
Mem [B800:(X+Y*Š)*2+1] := Color+Back*10h ;
End ;
K čemu to je? Je to rychlejší než pascalské gotoxy a write a
je možné zapisovat i za 25 řádek a 80 sloupec. Pro vás je však
důležité umět dostat za 25 řádek i kurzor. K tomu již GotoXY užít
musíme, napíšeme si ho ale sami, abychom nebyli omezeni Pascalem.
Přerušení 10h ( služby obrazovky ) poskytuje službu 02h - nastav
pozici kurzoru. Do registrů dh, dl se dá X, Y souřadnice, do BH
stránka obrazovky, do které se má zapsat. V praxi to vypadá takhle:
Var R : Registers ;
Procedure GotoXY ( X,Y : Byte ) ;
Begin
With R Do
Begin
AH := 2 ;
BH := 0 ; {případně aktivní stránka}
DL := X ;
DH := Y ;
End ;
Intr(10,R) ;
End ;
A nebo takhle:
Procedure Gotoxy ( X,Y : Byte ) ; Assembler ;
Asm
mov ah,2
xor bh,bh { nebo mov bh,číslo_stránky }
mov dl,x
mov dh,y
int 10h
end ;
Samozdřejmě lze zapsat i znak na místo kurzoru a provede se to
opět přes služby obrazovky. Slouží k tomu funkce 09h s atributem
nebo funkce 0ah bez atributu. Fce 0ah zachová atribut, který měl
předchozí znak na tomto místě. Paskalisté prominou, ale dále budu
uvádět pouze příklady v assembleru a jak na to s Pascalskými
registry snad každý pochopí sám. Obě fce používají BH jako číslo
stránky, AL jako hodnotu znaku ( ASCII ) a CX jako počet opakování.
Fce 09h navíc čte z registru BL atribut znaku. V praxi tedy takto:
Procedure WriteChar ( ASCII:Byte,C:Word /Attrib:Byte/ ;); Assembler;
Asm
mov ah,09h /mov ah,0ah/
mov al,ASCII
mov cx,x
xor bh,bh { mov bh,aktivní_stránka }
/mov bl,attrib/
int 10h
End ;
Pozor. Pokud dáte do CX opakování, znak se sice vypíše několikrát
vedle sebe, ale kurzor se neposune. Proto je to nepraktické, pokud
po každé klávese nechcete posouvat kurzor o znak doprava.
Nakonec si ukážeme, jak přes služby obrazovky vytisknout celý
řetězec. Je k tomu zapotřebí funkce 13h. Zde se použijí registry AL
jako formát zadávaného řetězce ( osvětlím později ), ES:BP začátek
řetězce, CX délka, DL a DH jako souřadnice počátku zobrazení a BH
jako stránka. Řetězec je možné zadat ve čtyřech formátech:
Hodnota AL Formát zadání Formát výstupu
0 Atribut bere z BL Nehýbe kurzorem
1 Atribut bere z BL Kurzor na konec řetězce
2 Formát znak, atribut, znak, atribut, ....
Nehýbe kurzorem
3 Formát znak, atribut, znak, atribut, ....
Kurzor na konec řetězce
Příklad psát nebudu, protože je příliš mnoho parametrů a záleží
na vás, co zvolíte za konstanty a co za parametry. Dovolím si ale
upozornit, že pointer v paskalu ukazuje na nultý znak stringu, kde
je uložena délka. Je proto nutné do CX načíst právě tento byte a
potom se posunout o byte dál. Někde v procedůrce by tedy mělo být:
mov ax,seg STRING
mov es,ax { do ES nejde zapsat přímo }
mov bp,offset STRING
xor ch,ch { vynulovat vrchní část CX }
mov cl,[es:bp] { zapsat do CX délku }
inc bp { posunout offset na začátke STRINGu }
Potom je již paskalský string reprodukován správně. Přerušení
10h samozdřejmě nabízí ještě řadu dalších služeb. Ty však nebudu
zmiňovat, nejsou tak důležité, a kdo je bude potřebovat, ten si je
dokáže zcela určitě najít. Tak. Celou dobu jsem se snažil vám
ukázat, že nejste omezeni žádným makrojazykem a můžete si psát co
chcete kam chcete do paměti. K čemu vám to ale bude, když vám na
monitoru stále bude oxidovat režim 80*25? Takže se podíváme na
nějaké neobyčejné textové režimy .
výheň