e-mail    Debatní kniha    Mapa stránek    Hlavní  
 perličky 
 

Jak na fonty pod DPMI

Petr Zahradník

Vdnešní době je nesmírně důležité ovládat národní prostředí -- ty tam jsou doby, kdy v programu stačily texty BEZ HACKU A CAREK. Program bez diakritiky nevypadá nijak kouzelně. Téměř rok je na trhu Borland Pascal 7.0, který umožňuje kompilovat programy pracující v chráněném režimu procesoru. Kdo poznal výhody tohoto režimu, kompiluje větší programy již zásadně pod DPMI. Samozřejmě tak činím i já.

Moc dobře si pamatuji, jak jsem byl zklamán, když jsem zjistil, že v chráněném režimu nepracuje přerušení INT 10H, které se používá pro načtení fontů do videokarty. Nastalo dilema, jak to řešit. V manuálech jsem moc informací o chráněném režimu nenašel, proto jsem tento problém provizorně řešil tak, že jsem z hlavní aplikace, která běžela v chráněném režimu, spustil malý prográmek v assembleru, který se spustil v reálném režimu a fonty načetl do videopaměti. Jenže programy, které se skládají z více než jednoho souboru EXE, nemám rád.

Proto jsem se neustále snažil problém fontů pod DPMI nějak vyřešit. Nejprve přes APRO, ale jak jsem brzy pochopil -- co je výhradnímu distributorovi Borlandu do nějakých problémů s Borland Pascalem, že? Bádal jsem ve zdrojových kódech a podařilo se mi objevit službu DPMI 300H, která simuluje přerušení reálného režimu. Protože dobře vím, kolik programátorů po tom pátrá, rozhodl jsem se o řešení tohoto velkého problému podělit se čtenáři Bajtu.

Jak jsem už uvedl, přerušení reálného režimu simuluje služba 300H DPMI, která se volá přerušením INT 31H. Registr AX je nutno nastavit na zmíněnou hodnotu 300H, v registru BL se předá číslo přerušení, které chceme simulovat, registr BH musí být nulový. Registr CX obsahuje počet přenášených slov do reálné paměti a registry ES:DI (selektor:offset) ukazují na datovou strukturu registrů pro reálný režim. Více je vidět ve vlastním programu. Maximálně jsem ho zjednodušil, a to na proceduru NahrajFonty, která nahraje fonty v chráněném režimu do videokarty VGA. Pro kartu EGA si tuto proceduru jistě každý sám přepíše. Parametr P je typu ukazatel a ukazuje na blok 4096 bajtů, kde jsou vlastní fonty načtené třeba z disku.

Procedura nejprve alokuje 4 KB (velikost fontů pro VGA) v oblasti prvního megabajtu paměti pomocí funkce GlobalDosAlloc (WinApi), tedy v oblasti, kam může zasahovat program spuštěný v reálném módu procesoru. To je nutné pro simulované INT 10H, které bude moci adresovat pouze první megabajt paměti. Potom se do této oblasti přesunou fonty, na které ukazuje zmíněný parametr $P$. Naplní se datová struktura registrů pro simulaci reálného režimu paramatery pro službu 11H přerušení INT 10H a zavolá se služba 300H DPMI, která provede vlastní simulaci. Potom se zase zruší alokovaný blok v prvním megabajtu paměti voláním funkce GlobalDosFree. Jak je vidět, není to ani tak složité, jak se zprvu zdálo, a věřím, že zveřejněním tohoto řešení vytrhnu trn z paty mnoha pokročilým programátorům pod DPMI.

uses
  WinApi;

{ Jednotka  WinApi je  potřebná pro  volání funkcí
 GlobalDosAlloc aGlobalDosFree }

procedure NahrajFonty(P: Pointer); near; assembler;
type
  TRR = record               { Typ datové struktury registrů }
    RealDI: Longint;         { pro reálný režim }
    RealSI: Longint;
    RealBP: Longint;
    Reserved: Longint;
    RealBX: Longint;
    RealDX: Longint;
    RealCX: Longint;
    RealAX: Longint;
    RealFlags: Word;
    RealES: Word;
    RealDS: Word;
    RealFS: Word;
    RealGS: Word;
    RealIP: Word;
    RealCS: Word;
    RealSP: Word;
    RealSS: Word;
  end;
var
  Segment: Word;             { Proměnné pro uchování ukazatele }
  Selector: Word;            { na alokovaný }
asm
        PUSH   BP        { Uložení důležitých registrů do
                         { zásobníku }
        PUSH   SP
        PUSH   SS
        PUSH   DS
        XOR    AX, AX        { Alokování 4096 bajtů v dolním
                             { 1MB }
        PUSH   AX            { První parametr tedy 0 }
        MOV    AX, 1000H     { Druhý parametr 4096 }
        PUSH   AX            { Předává se totiž velikost 
                             { Longint }
        CALL   GlobalDosAlloc     { Volání funkce alokace }
        MOV    Segment, DX        { Segment alokovaného bloku }
        MOV    Selector, AX       { Selektor alokovaného bloku }
        MOV    CX, 0              { Přesun 4096 bajtů fontů do }
        JMP    @2                 { tohoto alokovaného bloku }
  @1:   INC    CX
  @2:   LES    DI, P              { DI = offset fontů }
        ADD    DI, CX             { Přičti pozici }
        MOV    DL, ES:[DI]        { Přečtení znaku }
        MOV    AX, Selector       { Ulož selektor }
        PUSH   AX
        MOV    DI, CX             { DI = pozice }
        POP    ES                 { ES = selektor }
        MOV    ES:[DI], DL        { Zápis znaku do bloku }
        CMP    CX, 0FFFH          { Opakuj 4096x }
        JNE    @1                 
        MOV    DI, OFFSET RealModeRegs     { Offset registrů
                                           { reálného módu }
        MOV    AX, Segment
        MOV    WORD PTR [DI].TRR.RealES, AX { ES = segment
                                            { bloku fontů }
        MOV    WORD PTR [DI].TRR.RealBP, 0  { BP = offset
                                            { bloku fontů }
        MOV    WORD PTR [DI].TRR.RealAX, 1100H  { Standardní
                                                { obsazení }
        MOV    WORD PTR [DI].TRR.RealBX, 1000H  { registrů pro
                                                { volání }
        MOV    WORD PTR [DI].TRR.RealCX, 0100H  { služby 11H INT
                                                { 10H pro VGA}
        MOV    WORD PTR [DI].TRR.RealDX, 0     
        MOV    AX, DS             { ES = datový segment }
        MOV    ES, AX
        MOV    AX, 0300H          { Číslo služby pro simulaci
                                  { reál.přerušení}
        MOV    BX, 0010H          { Parametr pro INT 10H }
        XOR    CX, CX             { Žádná přenášená data }
        INT    31H                { Volání služby DPMI }
        PUSH   Selector           { Dealokace bloku pro fonty }
        CALL   GlobalDosFree      { Parametrem je selektor
                                  { alokovaného bloku}
        POP    DS                 { Vyzvednutí registrů ze
                                  { zásobníku }
        POP    SS
        POP    SP
        POP    BP
end;



Pascal - hlavní
Překladače
Vlastní články
Převzaté články
Věci na stáhnutí
Odkazy k tématu
BP7 buglist
Chyba Run-time 200

BASIC