Hlavní navigace

Grafická karta EGA: pouze mírný pokrok v mezích zákona (2. část)

25. 7. 2024
Doba čtení: 43 minut

Sdílet

 Autor: Pavel Tišnovský
Grafická karta EGA sice není ideální, ale nabízí mnohem větší flexibilitu, než tomu bylo u jejích předchůdců. Dnes se podíváme na výběr barev pro kreslení, použití uživatelských fontů a taktéž použití vlastní barvové palety.

Obsah

1. Grafická karta EGA: pouze mírný pokrok v mezích zákona (2. část)

2. Optimalizace podprogramu pro výběr bitových rovin pro zápis pixelů

3. Úplný zdrojový kód dnešního prvního demonstračního příkladu: vykreslení barevných pruhů s využitím 16 barev

4. Podprogram pro vykreslení pixelu s libovolnou barvou vybranou z barvové palety

5. Úplný zdrojový kód dnešního druhého demonstračního příkladu: úsečky v režimu 320×200

6. Úprava algoritmu pro vykreslení pixelů v režimu s 640 sloupci na obrazovém řádku

7. Úplný zdrojový kód dnešního třetího demonstračního příkladu: úsečky v režimu 640×350

8. Standardní znaková sada karty EGA

9. Získání tvarů znaků z GNU Unifontu

10. Programová modifikace znakové sady

11. Úplný zdrojový kód dnešního čtvrtého demonstračního příkladu: použití vlastní znakové sady

12. Výběr barev do barvové palety

13. Chování grafického režimu 320×200 pixelů při modifikaci barvové palety

14. Změna barvové palety a grafický režim s rozlišením 640×350 pixelů

15. Změna všech barev v paletě s využitím programové smyčky

16. Úplný zdrojový kód příkladu pro změnu všech barev v paletě

17. Změna barev v paletě jediným voláním služby BIOSu

18. Poslední demonstrační příklad: změna všech barev (včetně okraje) službou BIOSu

19. Repositář s demonstračními příklady

20. Odkazy na Internetu

1. Grafická karta EGA: pouze mírný pokrok v mezích zákona (2. část)

Na předchozí článek o grafické kartě EGA dnes navážeme. Nejprve si řekneme, jak lze zjednodušit a urychlit výběr bitových rovin při vykreslování grafiky s barvami. S touto problematikou souvisí i náš oblíbený problém – jak efektivně vykreslit jednotlivé pixely, tj. základní grafické primitivum. Dále se seznámíme s tím, jakým způsobem lze využít vlastní znakovou sadu v textových režimech, což je vlastně na platformě PC novinka, protože žádná z předchozích grafických karet (MDA, CGA, Hercules) tuto možnost nenabízely, jelikož bitové mapy znaků byly uloženy v ROM (většinou v EPROM, ovšem programovatelné mimo PC)*. A nezapomeneme ani na problematiku výběru barev do barvové palety, což je oblast, v níž se opět ukazují určitá omezení karty EGA, která vycházejí ze snahy o zpětnou kompatibilitu se staršími monitory určenými pro původní kartu CGA.

Obrázek 1: Známá hra Xenon 2: The megablast v šestnáctibarevném grafickém režimu karty EGA.

Poznámka: to, že MDA a Hercules (CGA vynechejme, ta není v tomto kontextu relevantní) nenabízely možnost programové změny znakové sady, mělo zajímavý důsledek – v našich končinách se slavné textové editory WordPerfect a WordStar ani zdaleka nestaly tak populární, jako v zemích, které si vystačily s rozšířenou znakovou sadou ASCII, která vyhovovala pro mnoho jazyků (viz horních 128 znaků).

2. Optimalizace podprogramu pro výběr bitových rovin pro zápis pixelů

Vraťme se na chvíli k předchozímu článku, v němž jsme si řekli, jakým způsobem je organizovaná video paměť karty EGA v nových grafických režimech. Video RAM je rozdělena do bitových rovin (bitplanes) a této technologii se z tohoto důvodu taktéž říká planární organizace nebo planární grafika. Data pixelu jsou zde konkrétně rozdělena do dvou či čtyř bitových rovin, přičemž v každé rovině je uložen jediný bit s kusem barvové informace o pixelu.

Pro výběr, do které bitové roviny nebo bitových rovin (libovolná kombinace) se má provést zápis, slouží následující podprogram, který zapíše požadovanou masku do jednoho z řídicích registrů karty EGA:

select_bitplane:
        mov  dx, ega_controller
        push ax
        mov  al, bitplane_selector
        out  dx, al         ; vyber registru sekvenceru
        pop  ax
        inc  dx
        out  dx, al         ; zapis masky bitovych rovin
        ret                 ; hotovo

Tento podprogram je ovšem možné zkrátit, přičemž využijeme (pro nás novou) instrukci XCHG (exchange), která dokáže prohodit obsah zdrojového a cílového registru nebo registru a paměti (bajt, nebo slovo). Výsledek se obejde bez nutnosti uchování registru AX na zásobníku a současně je ukázáno, že instrukce OUT DX, AX dokáže zapsat na dva osmibitové I/O porty, které leží za sebou. V tomto případě tedy na port s výběrem registru a datový port:

select_bitplane:
        mov  dx, ega_controller
        mov  ah, bitplane_selector
        xchg ah, al
        out  dx, ax         ; vyber registru sekvenceru
                            ; a zapis masky bitovych rovin
        ret                 ; hotovo
Poznámka: pro zjištění, jak dlouho trvají jednotlivé instrukce na procesoru Intel 8088/Intel 8086 je pravděpodobně nejlepším dostupným zdrojem dokument uložený na adrese http://aturing.umcs.maine­.edu/~meadow/courses/cos335/80×86-Integer-Instruction-Set-Clocks.pdf.

Obrázek 2: Další screenshot ze hry Xenon 2: The megablast běžící v grafickém režimu karty EGA.

3. Úplný zdrojový kód dnešního prvního demonstračního příkladu: vykreslení barevných pruhů s využitím 16 barev

Opět se podívejme, jak je v tomto seriálu zvykem, na úplný zdrojový kód příkladu, který po svém překladu assemblerem NASM a spuštění v emulátoru DOSu (nebo na původním HW) vykreslí následující obrázek:

Obrázek 3: Barevné pruhy vykreslené dnešním prvním demonstračním příkladem.

Kód tohoto příkladu vypadá následovně:

; Graficky rezim karty EGA s rozlisenim 320x200 pixelu.
; Zmena barvovych rovin, do kterych se zapisuje.
;
; preklad pomoci:
;     nasm -f bin -o ega.com ega_gfx_mode_bitplanes_2.asm
;
; nebo pouze:
;     nasm -o ega.com ega_gfx_mode_bitplanes_2.asm
 
 
;-----------------------------------------------------------------------------
 
; registry karty EGA/VGA
ega_controller    equ 0x3c4
bitplane_selector equ 0x02
 
 
; ukonceni procesu a navrat do DOSu
%macro exit 0
        mov     ah, 0x4c
        int     0x21
%endmacro
 
; vyprazdneni bufferu klavesnice a cekani na klavesu
%macro wait_key 0
        xor     ax, ax
        int     0x16
%endmacro
 
; nastaveni grafickeho rezimu
%macro gfx_mode 1
        mov     ah, 0
        mov     al, %1
        int     0x10
%endmacro
 
;-----------------------------------------------------------------------------
org  0x100        ; zacatek kodu pro programy typu COM (vzdy se zacina na 436)
 
start:
        gfx_mode 0x0d       ; nastaveni rezimu 320x200 se sestnacti barvami
        mov ax, 0xa000      ; video RAM v textovem rezimu
        mov es, ax
        xor di, di          ; nyni ES:DI obsahuje adresu prvniho pixelu ve video RAM
 
        xor al, al          ; maska bitovych rovin
        mov cl, 16          ; pocitadlo barevnych pruhu
opak:
        call draw_block_into_bitplanes
        loop opak
 
        wait_key            ; cekani na klavesu
        exit                ; navrat do DOSu
 
select_bitplane:
        mov  dx, ega_controller
        mov  ah, bitplane_selector
        xchg ah, al
        out  dx, ax         ; vyber registru sekvenceru
                            ; a zapis masky bitovych rovin
        ret                 ; hotovo
 
draw_block_into_bitplanes:
        push ax
        push cx
        call select_bitplane; maska bitovych rovin
        call draw_block
        add  di, 320*3/8    ; posun o nekolik radku nize
        pop  cx
        pop  ax
        inc  al             ; zmena masky
        ret                 ; hotovo
 
draw_block:
        mov cx, 320*9/8     ; pocet zapisovanych pixelu (ovsem pocitano v bajtech)
        mov al, 0xff        ; kod pixelu
        rep stosb
        ret

4. Podprogram pro vykreslení pixelu s libovolnou barvou vybranou z barvové palety

V tento okamžik již máme k dispozici všechny informace potřebné k tomu, abychom dokázali v libovolném novém grafickém režimu karty EGA vykreslit jednotlivé pixely:

  1. Díky lineárnímu adresování v rámci jedné bitové roviny umíme spočítat adresu pixelu
  2. Dokážeme nastavit bitové roviny na základě požadované barvy pixelu
  3. Umíme spočítat masku pixelu v rámci osmice pixelů (již jsme si otestovali na CGA i Herculesu)

Podprogram určený pro vykreslení pixelu akceptuje 16bitové (což je nyní již nutnost) souřadnice pixelu předávané v pracovních registrech AX a BX a taktéž barvu pixelu 0–15 předanou v pracovním registru CL:

; Vykresleni pixelu
; AX - x-ova souradnice
; BX - y-ova souradnice (staci len BL)
; CL - barva
putpixel:
        ...
        ...
        ...
 
        ret

Nejdříve na základě obsahu registru CL (barva pixelu) povolíme zápis do příslušných barvových rovin (se zachováním x-ové souřadnice pixelu předávané v registru AX):

        push ax
        mov al, cl         ; vyber bitove roviny nebo bitovych rovin
        call select_bitplane
        pop ax

Nastavíme segmentový registr ES na segment video RAM (již dobře známe):

        mov dx, 0xa000     ; zacatek stranky video RAM
        mov es, dx         ; nyni obsahuje ES stranku video RAM

Do CL se uloží informace použité později pro maskování:

        mov cl, al
        and cl, 7          ; pouze spodni 3 bity x-ove souradnice

V dalším kroku, a to bez operace násobení, vypočteme adresu pixelu součtem horizontálního posunu (v rámci jednoho obrazového řádku) a posunu vertikálního (vynásobení souřadnice y konstantou 40):

        shr ax, 1
        shr ax, 1
        shr ax, 1          ; x/8
        mov di, ax         ; horizontalni posun pocitany v bajtech
 
        mov ax, bx         ; y-ova souradnice
        shl ax, 1          ; y*2
        shl ax, 1          ; y*4
        shl ax, 1          ; y*8
        add di, ax         ; pricist cast y-oveho posunu
        shl ax, 1          ; y*16
        shl ax, 1          ; y*32
        add di, ax         ; pricist zbytek y-oveho posunu
                           ; -> y*8 + y*32 = y*40

Samotný zápis je nyní poněkud paradoxně snadnější, než tomu bylo u karet CGA a Hercules, protože nemusíme brát v úvahu prokládání obrazových řádků:

        mov al, 0x80       ; vypocitat masku pixelu
        shr al, cl
        or [es:di], al     ; vlastni vykresleni pixelu

Pokud ve smyčce vykreslíme úsečky z pixelů, dostaneme tento výsledek:

Obrázek 4: Barevné úsečky vykreslené z jednotlivých pixelů.

5. Úplný zdrojový kód dnešního druhého demonstračního příkladu: úsečky v režimu 320×200

Dnešní druhý demonstrační příklad vypadá následovně:

; Graficky rezim karty EGA s rozlisenim 320x200 pixelu.
; Zmena barvovych rovin, do kterych se zapisuje.
; Vykresleni barevnych usecek.
;
; preklad pomoci:
;     nasm -f bin -o ega.com ega_320x200_putpixel.asm
;
; nebo pouze:
;     nasm -o ega.com ega_320x200_putpixel.asm
 
 
;-----------------------------------------------------------------------------
 
; registry karty EGA/VGA
ega_controller    equ 0x3c4
bitplane_selector equ 0x02
 
 
; ukonceni procesu a navrat do DOSu
%macro exit 0
        mov     ah, 0x4c
        int     0x21
%endmacro
 
; vyprazdneni bufferu klavesnice a cekani na klavesu
%macro wait_key 0
        xor     ax, ax
        int     0x16
%endmacro
 
; nastaveni grafickeho rezimu
%macro gfx_mode 1
        mov     ah, 0
        mov     al, %1
        int     0x10
%endmacro
 
;-----------------------------------------------------------------------------
org  0x100        ; zacatek kodu pro programy typu COM (vzdy se zacina na 436)
 
start:
        gfx_mode 0x0d       ; nastaveni rezimu 320x200 se sestnacti barvami
        mov ax, 0xa000      ; video RAM v textovem rezimu
        mov es, ax
        xor di, di          ; nyni ES:DI obsahuje adresu prvniho pixelu ve video RAM
 
        mov ax, 0
opak:
        mov bx, ax          ; y-ová souřadnice
 
        push ax
        mov cl, 10          ; barva
        call putpixel       ; vykreslení pixelu
        pop ax
 
        push ax
        mov cl, 11          ; barva
        add ax, 10          ; horizontalni posun usecky
        call putpixel       ; vykreslení pixelu
        pop ax
 
        push ax
        mov cl, 12          ; barva
        add ax, 20          ; horizontalni posun usecky
        call putpixel       ; vykreslení pixelu
        pop ax
 
        inc ax              ; pusun x+=1, y+=1
        cmp ax, 200         ; hranice obrazovky?
        jne opak            ; ne-opakujeme
 
        wait_key            ; cekani na klavesu
        exit                ; navrat do DOSu
 
select_bitplane:
        mov  dx, ega_controller
        mov  ah, bitplane_selector
        xchg ah, al
        out  dx, ax         ; vyber registru sekvenceru
                            ; a zapis masky bitovych rovin
        ret                 ; hotovo
 
; Vykresleni pixelu
; AX - x-ova souradnice
; BX - y-ova souradnice (staci len BL)
; CL - barva
putpixel:
        push ax
        mov al, cl         ; vyber bitove roviny nebo bitovych rovin
        call select_bitplane
        pop ax
 
        mov dx, 0xa000     ; zacatek stranky video RAM
        mov es, dx         ; nyni obsahuje ES stranku video RAM
 
        mov cl, al
        and cl, 7          ; pouze spodni 3 bity x-ove souradnice
 
        shr ax, 1
        shr ax, 1
        shr ax, 1          ; x/8
        mov di, ax         ; horizontalni posun pocitany v bajtech
 
        mov ax, bx         ; y-ova souradnice
        shl ax, 1          ; y*2
        shl ax, 1          ; y*4
        shl ax, 1          ; y*8
        add di, ax         ; pricist cast y-oveho posunu
        shl ax, 1          ; y*16
        shl ax, 1          ; y*32
        add di, ax         ; pricist zbytek y-oveho posunu
                           ; -> y*8 + y*32 = y*40
 
        mov al, 0x80       ; vypocitat masku pixelu
        shr al, cl
        or [es:di], al     ; vlastni vykresleni pixelu
 
        ret

6. Úprava algoritmu pro vykreslení pixelů v režimu s 640 sloupci na obrazovém řádku

V případě, že budeme chtít upravit algoritmus pro vykreslení pixelů takovým způsobem, aby pracoval korektně i v grafických režimech s 640 sloupci (640×200 a 640×350), musíme provést jen nepatrnou úpravu – namísto násobení y-ové souřadnice konstantou 40 provedeme násobení konstantou 80, protože 640/8=80 (bajtů).

Připomeňme si, že původní kód pro násobení vypadal takto:

        mov ax, bx         ; y-ova souradnice
        shl ax, 1          ; y*2
        shl ax, 1          ; y*4
        shl ax, 1          ; y*8
        add di, ax         ; pricist cast y-oveho posunu
        shl ax, 1          ; y*16
        shl ax, 1          ; y*32
        add di, ax         ; pricist zbytek y-oveho posunu
                           ; -> y*8 + y*32 = y*40

Úprava pro režim 640×200/350 je až triviálně snadná, protože přidáme jeden bitový posun doleva:

        mov ax, bx         ; y-ova souradnice
        shl ax, 1          ; y*2
        shl ax, 1          ; y*4
        shl ax, 1          ; y*8
        shl ax, 1          ; y*16
        add di, ax         ; pricist cast y-oveho posunu
        shl ax, 1          ; y*32
        shl ax, 1          ; y*64
        add di, ax         ; pricist zbytek y-oveho posunu
                           ; -> y*16 + y*64 = y*80

Výsledek:

Obrázek 5: Barevné úsečky vykreslené z jednotlivých pixelů.

7. Úplný zdrojový kód dnešního třetího demonstračního příkladu: úsečky v režimu 640×350

Výsledný zdrojový kód se až na výše zmíněnou instrukci pro bitový posun, nijak zásadně nezmění, pouze nastavíme odlišný grafický režim a taktéž zvýšíme počet pixelů vykreslených v jedné úsečce z 200 na 350:

; Graficky rezim karty EGA s rozlisenim 640x350 pixelu.
; Zmena barvovych rovin, do kterych se zapisuje.
; Vykresleni barevnych usecek.
;
; preklad pomoci:
;     nasm -f bin -o ega.com ega_640x350_putpixel.asm
;
; nebo pouze:
;     nasm -o ega.com ega_640x350_putpixel.asm
 
 
;-----------------------------------------------------------------------------
 
; registry karty EGA/VGA
ega_controller    equ 0x3c4
bitplane_selector equ 0x02
 
 
; ukonceni procesu a navrat do DOSu
%macro exit 0
        mov     ah, 0x4c
        int     0x21
%endmacro
 
; vyprazdneni bufferu klavesnice a cekani na klavesu
%macro wait_key 0
        xor     ax, ax
        int     0x16
%endmacro
 
; nastaveni grafickeho rezimu
%macro gfx_mode 1
        mov     ah, 0
        mov     al, %1
        int     0x10
%endmacro
 
;-----------------------------------------------------------------------------
org  0x100        ; zacatek kodu pro programy typu COM (vzdy se zacina na 436)
 
start:
        gfx_mode 0x10       ; nastaveni rezimu 640x350 se sestnacti barvami
        mov ax, 0xa000      ; video RAM v textovem rezimu
        mov es, ax
        xor di, di          ; nyni ES:DI obsahuje adresu prvniho pixelu ve video RAM
 
        mov ax, 0
opak:
        mov bx, ax          ; y-ová souřadnice
 
        push ax
        mov cl, 10          ; barva
        call putpixel       ; vykreslení pixelu
        pop ax
 
        push ax
        mov cl, 11          ; barva
        add ax, 10          ; horizontalni posun usecky
        call putpixel       ; vykreslení pixelu
        pop ax
 
        push ax
        mov cl, 12          ; barva
        add ax, 20          ; horizontalni posun usecky
        call putpixel       ; vykreslení pixelu
        pop ax
 
        inc ax              ; pusun x+=1, y+=1
        cmp ax, 350         ; hranice obrazovky?
        jne opak            ; ne-opakujeme
 
        wait_key            ; cekani na klavesu
        exit                ; navrat do DOSu
 
select_bitplane:
        mov  dx, ega_controller
        mov  ah, bitplane_selector
        xchg ah, al
        out  dx, ax         ; vyber registru sekvenceru
                            ; a zapis masky bitovych rovin
        ret                 ; hotovo
 
; Vykresleni pixelu
; AX - x-ova souradnice
; BX - y-ova souradnice (staci len BL)
putpixel:
        push ax
        mov al, cl         ; vyber bitove roviny nebo bitovych rovin
        call select_bitplane
        pop ax
 
        mov dx, 0xa000     ; zacatek stranky video RAM
        mov es, dx         ; nyni obsahuje ES stranku video RAM
 
        mov cl, al
        and cl, 7          ; pouze spodni 3 bity x-ove souradnice
 
        shr ax, 1
        shr ax, 1
        shr ax, 1          ; x/8
        mov di, ax         ; horizontalni posun pocitany v bajtech
 
        mov ax, bx         ; y-ova souradnice
        shl ax, 1          ; y*2
        shl ax, 1          ; y*4
        shl ax, 1          ; y*8
        shl ax, 1          ; y*16
        add di, ax         ; pricist cast y-oveho posunu
        shl ax, 1          ; y*32
        shl ax, 1          ; y*64
        add di, ax         ; pricist zbytek y-oveho posunu
                           ; -> y*16 + y*64 = y*80
 
        mov al, 0x80       ; vypocitat masku pixelu
        shr al, cl
        or [es:di], al     ; vlastni vykresleni pixelu
 
        ret

8. Standardní znaková sada karty EGA

Již několikrát jsme si řekli, že původní karty pro PC, tedy jak MDA, tak i CGA (ale i Hercules), měly znakovou sadu používanou v textových režimech uschovánu v paměti ROM (většinou EPROM, ať již s okénkem nebo bez okénka) a tudíž nebylo zcela snadné ji měnit. A při výměně, například při potřebě použití českých nabodeníček, se pochopitelně přestaly zobrazovat původní znaky (různé rámečky atd.). Řešení přinesla právě až grafická karta EGA, která umožňovala kromě ROM sady (na originální EGA uložena od adresy 0×2230, ale na to se nedá spolehnout), uložení vlastních sad znaků přímo ve video RAM. Interně byla video RAM i v textových režimech rozdělena na bitové roviny: znaky, atributy a bitmapy fontů, to však při praktickém použití EGA můžeme do značné míry ignorovat a tvářit se, že textové režimy mají stejný formát, jako na MDA, CGA i Herculesu.

Jak vlastně vypadá standardní znaková sada EGA? Původní znaky vytvořila IBM a některé klony EGA mohou používat nepatrně odlišné znaky, ovšem základní znaky z ASCII by měly vypadat následovně:

Obrázek 6: Základní ASCII znaky zobrazené kartou EGA (resp. v tomto konkrétním případě emulátorem DOSBox).

Tento obrázek byl získán zcela jednoduchým programem:

; Textovy rezim karty EGA s rozlisenim 80x25 znaku.
; Vypis vsech standardnich ASCII znaku.
;
; preklad pomoci:
;     nasm -f bin -o ega.com ega_standard_font.asm
;
; nebo pouze:
;     nasm -o ega.com ega_standard_font.asm
 
 
;-----------------------------------------------------------------------------
 
; ukonceni procesu a navrat do DOSu
%macro exit 0
        mov     ah, 0x4c
        int     0x21
%endmacro
 
; vyprazdneni bufferu klavesnice a cekani na klavesu
%macro wait_key 0
        xor     ax, ax
        int     0x16
%endmacro
 
; nastaveni grafickeho rezimu
%macro gfx_mode 1
        mov     ah, 0
        mov     al, %1
        int     0x10
%endmacro
 
;-----------------------------------------------------------------------------
org  0x100        ; zacatek kodu pro programy typu COM (vzdy se zacina na 256)
 
start:
        gfx_mode 3      ; nastaveni standardniho textoveho rezimu 80x25 znaku
 
        mov ax, 0xb800  ; video RAM v textovem rezimu
        mov es, ax
        mov di, 0       ; nyni ES:DI obsahuje adresu prvniho znaku ve video RAM
 
        mov cx, 95      ; pocet zapisovanych znaku
        mov al, 32      ; kod zapisovaneho znaku
opak:
        stosb           ; zapis znaku
        inc al          ; dalsi znak
        inc di          ; preskocit atribut
        loop opak       ; opakujeme CX-krat
 
        wait_key        ; cekani na klavesu
        exit            ; navrat do DOSu

9. Získání tvarů znaků z GNU Unifontu

Zkusme si nyní načíst a zobrazit nějakou alternativní znakovou sadu. Vzhledem k tomu, že mnoho původních fontů má copyright, použijeme GNU Unifont. Ten obsahuje definice znaků v maskách 16×16 pixelů, ovšem základní ASCII znaky mají masku zmenšenou na 8×16 pixelů. A to je přesně ten formát, který potřebujeme. Postačuje si stáhnout .hex soubor s celou znakovou sadou a získat z ní 95 znaků ze standardní ASCII (teoreticky se jedná o 96 znaků, ovšem znak DEL již má odlišnou masku).

Soubor s 95 znaky ASCII vypadá takto:

0020:00000000000000000000000000000000
0021:00000000080808080808080008080000
0022:00002222222200000000000000000000
0023:000000001212127E24247E4848480000
0024:00000000083E4948380E09493E080000
0025:00000000314A4A340808162929460000
0026:000000001C2222141829454246390000
0027:00000808080800000000000000000000
0028:00000004080810101010101008080400
0029:00000020101008080808080810102000
002A:00000000000008492A1C2A4908000000
002B:0000000000000808087F080808000000
002C:00000000000000000000000018080810
002D:0000000000000000003C000000000000
002E:00000000000000000000000018180000
002F:00000000020204080810102040400000
0030:00000000182442464A52624224180000
0031:000000000818280808080808083E0000
0032:000000003C4242020C102040407E0000
0033:000000003C4242021C020242423C0000
0034:00000000040C142444447E0404040000
0035:000000007E4040407C020202423C0000
0036:000000001C2040407C424242423C0000
0037:000000007E0202040404080808080000
0038:000000003C4242423C424242423C0000
0039:000000003C4242423E02020204380000
003A:00000000000018180000001818000000
003B:00000000000018180000001808081000
003C:00000000000204081020100804020000
003D:000000000000007E0000007E00000000
003E:00000000004020100804081020400000
003F:000000003C4242020408080008080000
0040:000000001C224A565252524E201E0000
0041:0000000018242442427E424242420000
0042:000000007C4242427C424242427C0000
0043:000000003C42424040404042423C0000
0044:00000000784442424242424244780000
0045:000000007E4040407C404040407E0000
0046:000000007E4040407C40404040400000
0047:000000003C424240404E4242463A0000
0048:00000000424242427E42424242420000
0049:000000003E08080808080808083E0000
004A:000000001F0404040404044444380000
004B:00000000424448506060504844420000
004C:000000004040404040404040407E0000
004D:00000000424266665A5A424242420000
004E:0000000042626252524A4A4646420000
004F:000000003C42424242424242423C0000
0050:000000007C4242427C40404040400000
0051:000000003C4242424242425A663C0300
0052:000000007C4242427C48444442420000
0053:000000003C424240300C0242423C0000
0054:000000007F0808080808080808080000
0055:000000004242424242424242423C0000
0056:00000000414141222222141408080000
0057:00000000424242425A5A666642420000
0058:00000000424224241818242442420000
0059:00000000414122221408080808080000
005A:000000007E02020408102040407E0000
005B:0000000E080808080808080808080E00
005C:00000000404020101008080402020000
005D:00000070101010101010101010107000
005E:00001824420000000000000000000000
005F:00000000000000000000000000007F00
0060:00201008000000000000000000000000
0061:0000000000003C42023E4242463A0000
0062:0000004040405C6242424242625C0000
0063:0000000000003C4240404040423C0000
0064:0000000202023A4642424242463A0000
0065:0000000000003C42427E4040423C0000
0066:0000000C1010107C1010101010100000
0067:0000000000023A44444438203C42423C
0068:0000004040405C624242424242420000
0069:000000080800180808080808083E0000
006A:0000000404000C040404040404044830
006B:00000040404044485060504844420000
006C:000000180808080808080808083E0000
006D:00000000000076494949494949490000
006E:0000000000005C624242424242420000
006F:0000000000003C4242424242423C0000
0070:0000000000005C6242424242625C4040
0071:0000000000003A4642424242463A0202
0072:0000000000005C624240404040400000
0073:0000000000003C4240300C02423C0000
0074:000000001010107C10101010100C0000
0075:000000000000424242424242463A0000
0076:00000000000042424224242418180000
0077:00000000000041494949494949360000
0078:00000000000042422418182442420000
0079:0000000000004242424242261A02023C
007A:0000000000007E0204081020407E0000
007B:0000000C10100808102010080810100C
007C:00000808080808080808080808080808
007D:00000030080810100804081010080830
007E:00000031494600000000000000000000

Obsah tohoto souboru převedeme do binárního formátu tak, aby obsahoval skutečně pouze masky 8×16×95 (1520 bajtů). K tomu použijeme tento konvertor (který jsem napsal velmi rychle a neobsahuje žádné kontroly; není to produkční kód):

#include <stdio.h>
 
#define INPUT_FILE "font.hex"
#define OUTPUT_FILE "font.bin"
#define CHARACTERS 95
#define CHAR_HEIGHT 16
 
int main(void) {
    FILE *fin;
    FILE *fout;
    int i;
 
    fin = fopen(INPUT_FILE, "r");
    fout = fopen(OUTPUT_FILE, "wb");
 
    for (i = 0; i < CHARACTERS; i++) {
        int c;
        int scanline;
 
        printf("%d\n", i);
 
        /* skip to ':' */
        while ((c = fgetc(fin)) != ':') {
            /* read until hits ':' */
        }
 
        for (scanline = 0; scanline < CHAR_HEIGHT; scanline++) {
            int b;
            fscanf(fin, "%02x", &b);
            fputc(b, fout);
        }
 
        /* skip endline */
        while ((c = fgetc(fin)) != '\n') {
            /* read until hits '\n' */
        }
    }
 
    fclose(fin);
    fclose(fout);
}

Výsledný binární soubor font.bin využijeme v dalším demonstračním příkladu.

10. Programová modifikace znakové sady

Vyzkoušejme si nyní zobrazení fontu, který jsme získali právě popsanou konverzí. Binární soubor s fontem si přilinkujeme do výsledného souboru COM nám již známým způsobem:

font:
        incbin "font.bin"

Dále musíme v runtime získat adresu prvního bajtu tohoto binárního bloku a uložit ji do dvojice ES:BP, kde ji očekává BIOS. To je snadná operace:

        mov ax, cs
        mov es, ax
        mov bp, font    ; ES:BP obsabuje adresu fontu

Nyní nastavíme parametry, které služba BIOSu pro změnu fontu vyžaduje. Zejména je nutné vyplnit počet znaků, které se budou měnit (v našem případě 95 znaků, tj. vlastně celá základní ASCII), dále ASCII kód prvního měněného znaku (v našem případě mezera), index znakové sady 0..3 (můžeme přepínat mezi čtyřmi sadami, viz příští článek) a výška znaků. Tu nastavíme na 16 obrazových řádků, protože to odpovídá původnímu fontu a s konkrétním počtem řádků na obrazovce tato hodnota nemusí zcela souviset (je menší – jen 14 obrazových řádků):

        mov cx, 95      ; pocet menenych znaku
        mov dx, 32      ; ASCII kod prvniho meneneho znaku
        mov bl, 0       ; index znakove sady
        mov bh, 16      ; vyska znaku

V posledním kroku nastavíme číslo služby a podslužby, kterou voláme a službu zavoláme:

        mov ax, 0x1110  ; nacteni + nastaveni uzivatelskeho fontu
        int 0x10        ; provest operaci

Obrázek 7: Zobrazení modifikované znakové sady

11. Úplný zdrojový kód dnešního čtvrtého demonstračního příkladu: použití vlastní znakové sady

Opět se podívejme na to, jak by mohl vypadat příklad, který ve standardním textovém režimu použije nestandardní znakovou sadu. Od předchozího příkladu se odlišuje v tom, že volá funkci BIOSu (popsanou v desáté kapitole) pro inicializaci nestandardní znakové sady:

; Textovy rezim karty EGA s rozlisenim 80x25 znaku.
; Nastaveni vlastniho fontu.
;
; preklad pomoci:
;     nasm -f bin -o ega.com ega_custom_font.asm
;
; nebo pouze:
;     nasm -o ega.com ega_custom_font.asm
 
 
;-----------------------------------------------------------------------------
 
; ukonceni procesu a navrat do DOSu
%macro exit 0
        mov     ah, 0x4c
        int     0x21
%endmacro
 
; vyprazdneni bufferu klavesnice a cekani na klavesu
%macro wait_key 0
        xor     ax, ax
        int     0x16
%endmacro
 
; nastaveni grafickeho rezimu
%macro gfx_mode 1
        mov     ah, 0
        mov     al, %1
        int     0x10
%endmacro
 
;-----------------------------------------------------------------------------
org  0x100        ; zacatek kodu pro programy typu COM (vzdy se zacina na 256)
 
start:
        gfx_mode 3      ; nastaveni standardniho textoveho rezimu 80x25 znaku
 
        mov ax, 0xb800  ; video RAM v textovem rezimu
        mov es, ax
        mov di, 0       ; nyni ES:DI obsahuje adresu prvniho znaku ve video RAM
 
        mov cx, 95      ; pocet zapisovanych znaku
        mov al, 32      ; kod zapisovaneho znaku
opak:
        stosb           ; zapis znaku
        inc al          ; dalsi znak
        inc di          ; preskocit atribut
        loop opak       ; opakujeme CX-krat
 
        mov ax, cs
        mov es, ax
        mov bp, font    ; ES:BP obsabuje adresu fontu
 
        mov ax, 0x1110  ; nacteni + nastaveni uzivatelskeho fontu
        mov cx, 95      ; pocet menenych znaku
        mov dx, 32      ; ASCII kod prvniho meneneho znaku
        mov bl, 0       ; index znakove sady
        mov bh, 16      ; vyska znaku
        int 0x10        ; provest operaci
 
        wait_key        ; cekani na klavesu
        exit            ; navrat do DOSu
 
font:
        incbin "font.bin"

12. Výběr barev do barvové palety

Grafická karta EGA dokáže současně zobrazit šestnáct barev umístěných v barvové paletě (ovšem s omezeními, o kterých se zmíníme dále). Těchto šestnáct barev již není konstantních tak, jako tomu bylo u CGA, protože nabízená barvová škála obsahuje celkem 64 barvových odstínů. Jak se ale k tomuto číslu došlo? Pro každou barvovou složku RGB můžeme specifikovat její nulovou intenzitu, 1/3 intenzitu, 2/3 intenzitu nebo 100% intenzitu. To znamená, že pro každou barvovou složku existují čtyři možnosti a výsledkem kombinace barvových složek je 4×4×4=64 podporovaných barvových odstínů.

Barvový odstín se do barvové palety (se šestnácti místy) přidává službou BIOSu 0×10h (video BIOS). Konkrétní číslo služby a podslužby je 0×1000 (předáno v registru AX), index barvy 0..15 se předává v registru BL a v registru BH je barva určena bitovou maskou 0b00rgbRGB, kde malé písmeno značí 1/3 intenzitu (pokud je bit roven jedné) a velké písmeno 2/3 intenzitu (opět, pokud je roven jedné). Například tmavě šedá barva bude mít 1/3 intenzitu všech tří barvových složek a bude tedy určena hodnotou 0b00111000. Takovou barvu přidáme do barvové palety následovně:

        mov ax, 0x1000
        mov bl, 1           ; index barvy
        mov bh, 0b111000    ; tmave seda
        int 0x10            ; volani sluzby BIOSu pro zmenu jedne barvy
Poznámka: u VGA je všechno jinak :-)

Pokusme se tedy změnit barvovou paletu tak, aby se zobrazily tyto pruhy:

Obrázek 8: Pruhy s barvami, které umístíme do barvové palety.

Barvová paleta by tedy měla obsahovat postupně tyto barvy:

0b000000         ; cerna (pozadi)
0b111000         ; tmave seda
0b000111         ; svetle seda
0b111111         ; bila
 
0b010000         ; tmave zelena
0b000010         ; stredne zelena
0b010010         ; svetle zelena
 
0b100000         ; tmave cervena
0b000100         ; stredne cervena
0b100100         ; svetle cervena
 
0b001000         ; tmave modra
0b000001         ; stredne modra
0b001001         ; svetle modra
 
0b110000         ; tmave hneda
0b000110         ; svetle hneda
0b110110         ; zluta

13. Chování grafického režimu 320×200 pixelů při modifikaci barvové palety

Pokud se ovšem pokusíme barvovou paletu nastavit na hodnoty vypsané výše, bude výsledek v některých případech dosti odlišný:

Obrázek 9: Barvová paleta v grafickém režimu 320×200 pixelů.

Co se změnilo? V režimu s 200 obrazovými řádky se předpokládá, že je připojen CGA monitor, který dokáže zobrazit osm základních barev ve dvou intenzitách, ovšem nedokáže již měnit intenzity individuálních barvových složek. To souvisí s již minule zmíněnými změnami v zapojení monitoru:

Pin CGA EGA
1 GND GND
2 GND 2/3 Red
3 Red 1/3 Red
4 Green 1/3 Green
5 Blue 1/3 Blue
6 Intenzita 2/3 Green
7 Rezervováno 2/3 Blue
8 H-sync H-sync
9 V-sync V-sync

Navíc CGA monitor obsahuje speciální obvod pro zobrazení hnědé namísto tmavě žluté (což je ve skutečnosti stejná barva, ale odlišný odstín). I to můžeme na obrázku číslo 9 vidět. DOSBox toto chování plně emuluje. A jedná se o jeden z důvodů, proč většina her určených pro kartu CGA a rozlišení 320×200 pixelů, používá původní barvovou paletu CGA – v takovém případě bude vše bezpečné a nedojde k případnému „odpálení“ výstupu karty EGA (červená složka, která může být v CGA monitoru uzemněna).

Výše uvedený obrázek číslo 9 vznikne po překladu a spuštění následujícího příkladu (individuální nastavení barev posléze změníme, zde je pouzito proto, aby byl kód sice dlouhý, ale dobře pochopitelný):

; Graficky rezim karty EGA s rozlisenim 320x200 pixelu.
; Zmena barvovych rovin, do kterych se zapisuje.
; Konfigurace barvove palety.
;
; preklad pomoci:
;     nasm -f bin -o ega.com ega_palette_1.asm
;
; nebo pouze:
;     nasm -o ega.com ega_palette_1.asm
 
 
;-----------------------------------------------------------------------------
 
; registry karty EGA/VGA
ega_controller    equ 0x3c4
bitplane_selector equ 0x02
 
 
; ukonceni procesu a navrat do DOSu
%macro exit 0
        mov     ah, 0x4c
        int     0x21
%endmacro
 
; vyprazdneni bufferu klavesnice a cekani na klavesu
%macro wait_key 0
        xor     ax, ax
        int     0x16
%endmacro
 
; nastaveni grafickeho rezimu
%macro gfx_mode 1
        mov     ah, 0
        mov     al, %1
        int     0x10
%endmacro
 
;-----------------------------------------------------------------------------
org  0x100        ; zacatek kodu pro programy typu COM (vzdy se zacina na 436)
 
start:
        gfx_mode 0x0d       ; nastaveni rezimu 320x200 se sestnacti barvami
        mov ax, 0xa000      ; video RAM v textovem rezimu
        mov es, ax
        xor di, di          ; nyni ES:DI obsahuje adresu prvniho pixelu ve video RAM
 
        xor al, al          ; maska bitovych rovin
        mov cl, 16          ; pocitadlo barevnych pruhu
opak:
        call draw_block_into_bitplanes
        loop opak
 
        wait_key            ; cekani na klavesu
 
        mov ax, 0x1000
 
        mov bl, 1           ; index barvy
        mov bh, 0b111000    ; tmave seda
        int 0x10            ; volani sluzby BIOSu pro zmenu jedne barvy
 
        mov bl, 2           ; index barvy
        mov bh, 0b000111    ; svetle seda
        int 0x10            ; volani sluzby BIOSu pro zmenu jedne barvy
 
        mov bl, 3           ; index barvy
        mov bh, 0b111111    ; bila
        int 0x10            ; volani sluzby BIOSu pro zmenu jedne barvy
 
        mov bl, 4           ; index barvy
        mov bh, 0b010000    ; tmave zelena
        int 0x10            ; volani sluzby BIOSu pro zmenu jedne barvy
 
        mov bl, 5           ; index barvy
        mov bh, 0b000010    ; stredne zelena
        int 0x10            ; volani sluzby BIOSu pro zmenu jedne barvy
 
        mov bl, 6           ; index barvy
        mov bh, 0b010010    ; svetle zelena
        int 0x10            ; volani sluzby BIOSu pro zmenu jedne barvy
 
        mov bl, 7           ; index barvy
        mov bh, 0b100000    ; tmave cervena
        int 0x10            ; volani sluzby BIOSu pro zmenu jedne barvy
 
        mov bl, 8           ; index barvy
        mov bh, 0b000100    ; stredne cervena
        int 0x10            ; volani sluzby BIOSu pro zmenu jedne barvy
 
        mov bl, 9           ; index barvy
        mov bh, 0b100100    ; svetle cervena
        int 0x10            ; volani sluzby BIOSu pro zmenu jedne barvy
 
        mov bl, 10          ; index barvy
        mov bh, 0b001000    ; tmave modra
        int 0x10            ; volani sluzby BIOSu pro zmenu jedne barvy
 
        mov bl, 11          ; index barvy
        mov bh, 0b000001    ; stredne modra
        int 0x10            ; volani sluzby BIOSu pro zmenu jedne barvy
 
        mov bl, 12          ; index barvy
        mov bh, 0b001001    ; svetle modra
        int 0x10            ; volani sluzby BIOSu pro zmenu jedne barvy
 
        mov bl, 13          ; index barvy
        mov bh, 0b110000    ; tmave hneda
        int 0x10            ; volani sluzby BIOSu pro zmenu jedne barvy
 
        mov bl, 14          ; index barvy
        mov bh, 0b000110    ; svetle hneda
        int 0x10            ; volani sluzby BIOSu pro zmenu jedne barvy
 
        mov bl, 15          ; index barvy
        mov bh, 0b110110    ; zluta
        int 0x10            ; volani sluzby BIOSu pro zmenu jedne barvy
 
        wait_key            ; cekani na klavesu
        exit                ; navrat do DOSu
 
select_bitplane:
        mov  dx, ega_controller
        mov  ah, bitplane_selector
        xchg ah, al
        out  dx, ax         ; vyber registru sekvenceru
                            ; a zapis masky bitovych rovin
        ret                 ; hotovo
 
draw_block_into_bitplanes:
        push ax
        push cx
        call select_bitplane; maska bitovych rovin
        call draw_block
        add  di, 320*3/8    ; posun o nekolik radku nize
        pop  cx
        pop  ax
        inc  al             ; zmena masky
        ret                 ; hotovo
 
draw_block:
        mov cx, 320*9/8     ; pocet zapisovanych pixelu (ovsem pocitano v bajtech)
        mov al, 0xff        ; kod pixelu
        rep stosb
        ret

14. Změna barvové palety a grafický režim s rozlišením 640×350 pixelů

V případě, že naprosto stejnou barvovou paletu nastavíme v režimu 640×200, dostaneme stejný (špatný) výsledek jako u režimu 320×200, protože nezáleží na horizontálním rozlišení, ale na počtu obrazových řádků (200=kompatibilita s CGA, 350=EGA monitor). Takže se pokusme zobrazit si barvové pruhy s využitím vlastní palety v nejvyšší režimu karty EGA, tedy konkrétně v grafickém režimu s rozlišením 640×350 pixelů. Nyní bude výsledek plně odpovídat nastavené barvové paletě, protože není nutné dodržovat zpětnou kompatibilitu (CGA monitory nedokážou pracovat s 350 obrazovými řádky):

Obrázek 10: Barvová paleta v grafickém režimu 640×350 pixelů.

A pro jistotu si zopakujme, tak bude tento příklad vypadat:

; Graficky rezim karty EGA s rozlisenim 640x350 pixelu.
; Zmena barvovych rovin, do kterych se zapisuje.
; Konfigurace barvove palety.
;
; preklad pomoci:
;     nasm -f bin -o ega.com ega_palette_2.asm
;
; nebo pouze:
;     nasm -o ega.com ega_palette_2.asm
 
 
;-----------------------------------------------------------------------------
 
; registry karty EGA/VGA
ega_controller    equ 0x3c4
bitplane_selector equ 0x02
 
 
; ukonceni procesu a navrat do DOSu
%macro exit 0
        mov     ah, 0x4c
        int     0x21
%endmacro
 
; vyprazdneni bufferu klavesnice a cekani na klavesu
%macro wait_key 0
        xor     ax, ax
        int     0x16
%endmacro
 
; nastaveni grafickeho rezimu
%macro gfx_mode 1
        mov     ah, 0
        mov     al, %1
        int     0x10
%endmacro
 
;-----------------------------------------------------------------------------
org  0x100        ; zacatek kodu pro programy typu COM (vzdy se zacina na 436)
 
start:
        gfx_mode 0x10       ; nastaveni rezimu 640x200 se sestnacti barvami
        mov ax, 0xa000      ; video RAM v textovem rezimu
        mov es, ax
        xor di, di          ; nyni ES:DI obsahuje adresu prvniho pixelu ve video RAM
 
        xor al, al          ; maska bitovych rovin
        mov cl, 16          ; pocitadlo barevnych pruhu
opak:
        call draw_block_into_bitplanes
        loop opak
 
        wait_key            ; cekani na klavesu
 
        mov ax, 0x1000      ; cislo sluzby a podsluzby BIOSu
 
        mov bl, 1           ; index barvy
        mov bh, 0b111000    ; tmave seda
        int 0x10            ; volani sluzby BIOSu pro zmenu jedne barvy
 
        mov bl, 2           ; index barvy
        mov bh, 0b000111    ; svetle seda
        int 0x10            ; volani sluzby BIOSu pro zmenu jedne barvy
 
        mov bl, 3           ; index barvy
        mov bh, 0b111111    ; bila
        int 0x10            ; volani sluzby BIOSu pro zmenu jedne barvy
 
        mov bl, 4           ; index barvy
        mov bh, 0b010000    ; tmave zelena
        int 0x10            ; volani sluzby BIOSu pro zmenu jedne barvy
 
        mov bl, 5           ; index barvy
        mov bh, 0b000010    ; stredne zelena
        int 0x10            ; volani sluzby BIOSu pro zmenu jedne barvy
 
        mov bl, 6           ; index barvy
        mov bh, 0b010010    ; svetle zelena
        int 0x10            ; volani sluzby BIOSu pro zmenu jedne barvy
 
        mov bl, 7           ; index barvy
        mov bh, 0b100000    ; tmave cervena
        int 0x10            ; volani sluzby BIOSu pro zmenu jedne barvy
 
        mov bl, 8           ; index barvy
        mov bh, 0b000100    ; stredne cervena
        int 0x10            ; volani sluzby BIOSu pro zmenu jedne barvy
 
        mov bl, 9           ; index barvy
        mov bh, 0b100100    ; svetle cervena
        int 0x10            ; volani sluzby BIOSu pro zmenu jedne barvy
 
        mov bl, 10          ; index barvy
        mov bh, 0b001000    ; tmave modra
        int 0x10            ; volani sluzby BIOSu pro zmenu jedne barvy
 
        mov bl, 11          ; index barvy
        mov bh, 0b000001    ; stredne modra
        int 0x10            ; volani sluzby BIOSu pro zmenu jedne barvy
 
        mov bl, 12          ; index barvy
        mov bh, 0b001001    ; svetle modra
        int 0x10            ; volani sluzby BIOSu pro zmenu jedne barvy
 
        mov bl, 13          ; index barvy
        mov bh, 0b110000    ; tmave hneda
        int 0x10            ; volani sluzby BIOSu pro zmenu jedne barvy
 
        mov bl, 14          ; index barvy
        mov bh, 0b000110    ; svetle hneda
        int 0x10            ; volani sluzby BIOSu pro zmenu jedne barvy
 
        mov bl, 15          ; index barvy
        mov bh, 0b110110    ; zluta
        int 0x10            ; volani sluzby BIOSu pro zmenu jedne barvy
 
        wait_key            ; cekani na klavesu
        exit                ; navrat do DOSu
 
select_bitplane:
        mov  dx, ega_controller
        mov  ah, bitplane_selector
        xchg ah, al
        out  dx, ax         ; vyber registru sekvenceru
                            ; a zapis masky bitovych rovin
        ret                 ; hotovo
 
draw_block_into_bitplanes:
        push ax
        push cx
        call select_bitplane; maska bitovych rovin
        call draw_block
        add  di, 640*3/8    ; posun o nekolik radku nize
        pop  cx
        pop  ax
        inc  al             ; zmena masky
        ret                 ; hotovo
 
draw_block:
        mov cx, 640*9/4     ; pocet zapisovanych pixelu (ovsem pocitano v bajtech)
        mov al, 0xff        ; kod pixelu
        rep stosb
        ret

15. Změna všech barev v paletě s využitím programové smyčky

To, jakým způsobem jsme postupně měnili barvy v paletě, nebylo zcela ideální řešení, protože se opakovaly stále ty stejné instrukce. A v případě, že by barev bylo 256, by už bylo toto řešení zcela absurdní. Pokusme se tedy o lepší řešení. Nejdříve si kdekoli v kódovém segmentu vytvoříme tabulku šestnácti barev, tedy včetně barvy pozadí). To je v NASMu snadné:

palette:                    ; barvova paleta bez barvy okraje
        db 0b000000         ; cerna (pozadi)
        db 0b111000         ; tmave seda
        db 0b000111         ; svetle seda
        db 0b111111         ; bila
        db 0b010000         ; tmave zelena
        db 0b000010         ; stredne zelena
        db 0b010010         ; svetle zelena
        db 0b100000         ; tmave cervena
        db 0b000100         ; stredne cervena
        db 0b100100         ; svetle cervena
        db 0b001000         ; tmave modra
        db 0b000001         ; stredne modra
        db 0b001001         ; svetle modra
        db 0b110000         ; tmave hneda
        db 0b000110         ; svetle hneda
        db 0b110110         ; zluta

Nyní nám postačuje volat již známou službu BIOSu a při každém volání korektně naplnit registr BH hodnotou načtenou z tabulky. Jedno z řešení, které v tomto případě není založeno na instrukci lodsb (používá odlišné registry), by mohlo vypadat například takto:

        mov ax, 0x1000      ; cislo sluzby a podsluzby BIOSu
        mov si, palette
        mov bl, 0           ; index barvy
next_color:
        mov bh, [cs:si]     ; hodnota barvy s indexem v BL
        int 0x10            ; zmena barvy
        inc bl              ; modifikace indexu
        inc si              ; modifikace adresy
        cmp bl, 16
        jne next_color      ; dalsi barva
Poznámka: nyní si můžete sami vyzkoušet, jestli není výhodnější použít pracovní registr CL ve funkci počitadla a tudíž namísto CMP+JNE použít instrukci LOOP. Tato úprava je jednoduchá a vyžaduje přidání jedné instrukce a odstranění dvou jiných instrukcí.

Zkontrolujeme výsledek:

Obrázek 11: Výsledek běhu upraveného příkladu, tentokrát založeného na použití programové smyčky.

16. Úplný zdrojový kód příkladu pro změnu všech barev v paletě

Pro úplnost si ukažme, jak se celý program nepatrně zkrátil zavedením tabulky barev a programové smyčky:

; Graficky rezim karty EGA s rozlisenim 640x350 pixelu.
; Zmena barvovych rovin, do kterych se zapisuje.
; Konfigurace barvove palety.
;
; preklad pomoci:
;     nasm -f bin -o ega.com ega_palette_3.asm
;
; nebo pouze:
;     nasm -o ega.com ega_palette_3.asm
 
 
;-----------------------------------------------------------------------------
 
; registry karty EGA/VGA
ega_controller    equ 0x3c4
bitplane_selector equ 0x02
 
 
; ukonceni procesu a navrat do DOSu
%macro exit 0
        mov     ah, 0x4c
        int     0x21
%endmacro
 
; vyprazdneni bufferu klavesnice a cekani na klavesu
%macro wait_key 0
        xor     ax, ax
        int     0x16
%endmacro
 
; nastaveni grafickeho rezimu
%macro gfx_mode 1
        mov     ah, 0
        mov     al, %1
        int     0x10
%endmacro
 
;-----------------------------------------------------------------------------
org  0x100        ; zacatek kodu pro programy typu COM (vzdy se zacina na 436)
 
start:
        gfx_mode 0x10       ; nastaveni rezimu 640x200 se sestnacti barvami
        mov ax, 0xa000      ; video RAM v textovem rezimu
        mov es, ax
        xor di, di          ; nyni ES:DI obsahuje adresu prvniho pixelu ve video RAM
 
        xor al, al          ; maska bitovych rovin
        mov cl, 16          ; pocitadlo barevnych pruhu
opak:
        call draw_block_into_bitplanes
        loop opak
 
        wait_key            ; cekani na klavesu
 
        mov ax, 0x1000      ; cislo sluzby a podsluzby BIOSu
        mov si, palette
        mov bl, 0           ; index barvy
next_color:
        mov bh, [cs:si]     ; hodnota barvy s indexem v BL
        int 0x10            ; zmena barvy
        inc bl              ; modifikace indexu
        inc si              ; modifikace adresy
        cmp bl, 16
        jne next_color      ; dalsi barva
 
        wait_key            ; cekani na klavesu
        exit                ; navrat do DOSu
 
palette:                    ; barvova paleta bez barvy okraje
        db 0b000000         ; cerna (pozadi)
        db 0b111000         ; tmave seda
        db 0b000111         ; svetle seda
        db 0b111111         ; bila
        db 0b010000         ; tmave zelena
        db 0b000010         ; stredne zelena
        db 0b010010         ; svetle zelena
        db 0b100000         ; tmave cervena
        db 0b000100         ; stredne cervena
        db 0b100100         ; svetle cervena
        db 0b001000         ; tmave modra
        db 0b000001         ; stredne modra
        db 0b001001         ; svetle modra
        db 0b110000         ; tmave hneda
        db 0b000110         ; svetle hneda
        db 0b110110         ; zluta
 
select_bitplane:
        mov  dx, ega_controller
        mov  ah, bitplane_selector
        xchg ah, al
        out  dx, ax         ; vyber registru sekvenceru
                            ; a zapis masky bitovych rovin
        ret                 ; hotovo
 
draw_block_into_bitplanes:
        push ax
        push cx
        call select_bitplane; maska bitovych rovin
        call draw_block
        add  di, 640*3/8    ; posun o nekolik radku nize
        pop  cx
        pop  ax
        inc  al             ; zmena masky
        ret                 ; hotovo
 
draw_block:
        mov cx, 640*9/4     ; pocet zapisovanych pixelu (ovsem pocitano v bajtech)
        mov al, 0xff        ; kod pixelu
        rep stosb
        ret

17. Změna barev v paletě jediným voláním služby BIOSu

V praxi se velmi často setkáme s nutností změny celé barvové palety, takže se nabízí otázka, jestli všichni vývojáři museli neustále opakovat programovou smyčku, kterou jsme si ukázali výše. Odpovědí je – nemuseli, protože BIOS grafické karty EGA nám nabízí k tomu určenou službu, která doplňuje službu pro změnu jediné barvy. Tato služba (+ podslužba) má číslo 0×1002 a vyžaduje, aby v registrovém páru ES:DX (pozor! skutečně DX a nikoli DI nebo BX, jak bychom logicky očekávali) byl uložen ukazatel na tabulku se sedmnácti barvami. Ona „divná“ sedmnáctá barva je barvou okraje (overscan border), které některé monitory podporují.

Namísto vlastní programové smyčky tedy postačuje napsat:

        mov ax, cs
        mov es, ax
        mov dx, palette     ; ES:BX obsahuje adresu barvove palety
        mov ax, 0x1002      ; cislo sluzby a podsluzby BIOSu
        int 0x10            ; volani sluzby BIOSu

18. Poslední demonstrační příklad: změna všech barev (včetně okraje) službou BIOSu

V dnešním posledním demonstračním příkladu je ukázán postup popsaný v předchozí kapitole, tj. změna všech barev v paletě, a to včetně barvy okraje na těch monitorech, které okraj zobrazují. Výsledek je kratší, než tomu bylo v předchozích třech demonstračních příkladech:

; Graficky rezim karty EGA s rozlisenim 640x350 pixelu.
; Zmena barvovych rovin, do kterych se zapisuje.
; Konfigurace barvove palety jedinym volanim prislusne sluzby.
;
; preklad pomoci:
;     nasm -f bin -o ega.com ega_palette_4.asm
;
; nebo pouze:
;     nasm -o ega.com ega_palette_4.asm
 
 
;-----------------------------------------------------------------------------
 
; registry karty EGA/VGA
ega_controller    equ 0x3c4
bitplane_selector equ 0x02
 
 
; ukonceni procesu a navrat do DOSu
%macro exit 0
        mov     ah, 0x4c
        int     0x21
%endmacro
 
; vyprazdneni bufferu klavesnice a cekani na klavesu
%macro wait_key 0
        xor     ax, ax
        int     0x16
%endmacro
 
; nastaveni grafickeho rezimu
%macro gfx_mode 1
        mov     ah, 0
        mov     al, %1
        int     0x10
%endmacro
 
;-----------------------------------------------------------------------------
org  0x100        ; zacatek kodu pro programy typu COM (vzdy se zacina na 436)
 
start:
        gfx_mode 0x10       ; nastaveni rezimu 640x200 se sestnacti barvami
        mov ax, 0xa000      ; video RAM v textovem rezimu
        mov es, ax
        xor di, di          ; nyni ES:DI obsahuje adresu prvniho pixelu ve video RAM
 
        xor al, al          ; maska bitovych rovin
        mov cl, 16          ; pocitadlo barevnych pruhu
opak:
        call draw_block_into_bitplanes
        loop opak
 
        wait_key            ; cekani na klavesu
 
        mov ax, cs
        mov es, ax
        mov dx, palette     ; ES:BX obsahuje adresu barvove palety
        mov ax, 0x1002      ; cislo sluzby a podsluzby BIOSu
        int 0x10            ; volani sluzby BIOSu
 
        wait_key            ; cekani na klavesu
        exit                ; navrat do DOSu
 
palette:                    ; barvova paleta i s barvou okraje
        db 0b000000         ; cerna (pozadi)
        db 0b111000         ; tmave seda
        db 0b000111         ; svetle seda
        db 0b111111         ; bila
        db 0b010000         ; tmave zelena
        db 0b000010         ; stredne zelena
        db 0b010010         ; svetle zelena
        db 0b100000         ; tmave cervena
        db 0b000100         ; stredne cervena
        db 0b100100         ; svetle cervena
        db 0b001000         ; tmave modra
        db 0b000001         ; stredne modra
        db 0b001001         ; svetle modra
        db 0b110000         ; tmave hneda
        db 0b000110         ; svetle hneda
        db 0b110110         ; zluta
        db 0b111111         ; okraj
 
select_bitplane:
        mov  dx, ega_controller
        mov  ah, bitplane_selector
        xchg ah, al
        out  dx, ax         ; vyber registru sekvenceru
                            ; a zapis masky bitovych rovin
        ret                 ; hotovo
 
draw_block_into_bitplanes:
        push ax
        push cx
        call select_bitplane; maska bitovych rovin
        call draw_block
        add  di, 640*3/8    ; posun o nekolik radku nize
        pop  cx
        pop  ax
        inc  al             ; zmena masky
        ret                 ; hotovo
 
draw_block:
        mov cx, 640*9/4     ; pocet zapisovanych pixelu (ovsem pocitano v bajtech)
        mov al, 0xff        ; kod pixelu
        rep stosb
        ret

19. Repositář s demonstračními příklady

Demonstrační příklady napsané v assembleru, které jsou určené pro překlad pomocí assembleru NASM, byly uložen do Git repositáře, který je dostupný na adrese https://github.com/tisnik/8bit-fame. Jednotlivé demonstrační příklady si můžete v případě potřeby stáhnout i jednotlivě bez nutnosti klonovat celý (dnes již poměrně rozsáhlý) repositář:

# Příklad Stručný popis Adresa
1 hello.asm program typu „Hello world“ naprogramovaný v assembleru pro systém DOS https://github.com/tisnik/8bit-fame/blob/master/pc-dos/hello.asm
2 hello_shorter.asm kratší varianta výskoku z procesu zpět do DOSu https://github.com/tisnik/8bit-fame/blob/master/pc-dos/hello_shorter.asm
3 hello_wait.asm čekání na stisk klávesy https://github.com/tisnik/8bit-fame/blob/master/pc-dos/hello_wait.asm
4 hello_macros.asm realizace jednotlivých částí programu makrem https://github.com/tisnik/8bit-fame/blob/master/pc-dos/hello_macros.asm
       
5 gfx4_putpixel.asm vykreslení pixelu v grafickém režimu 4 https://github.com/tisnik/8bit-fame/blob/master/pc-dos/gfx4_putpixel.asm
6 gfx6_putpixel.asm vykreslení pixelu v grafickém režimu 6 https://github.com/tisnik/8bit-fame/blob/master/pc-dos/gfx6_putpixel.asm
7 gfx4_line.asm vykreslení úsečky v grafickém režimu 4 https://github.com/tisnik/8bit-fame/blob/master/pc-dos/gfx4_line.asm
8 gfx6_line.asm vykreslení úsečky v grafickém režimu 6 https://github.com/tisnik/8bit-fame/blob/master/pc-dos/gfx6_line.asm
       
9 gfx6_fill1.asm vyplnění obrazovky v grafickém režimu, základní varianta https://github.com/tisnik/8bit-fame/blob/master/pc-dos/gfx6_fill1.asm
10 gfx6_fill2.asm vyplnění obrazovky v grafickém režimu, varianta s instrukcí LOOP https://github.com/tisnik/8bit-fame/blob/master/pc-dos/gfx6_fill2.asm
11 gfx6_fill3.asm vyplnění obrazovky instrukcí REP STOSB https://github.com/tisnik/8bit-fame/blob/master/pc-dos/gfx6_fill3.asm
12 gfx6_fill4.asm vyplnění obrazovky, synchronizace vykreslování s paprskem https://github.com/tisnik/8bit-fame/blob/master/pc-dos/gfx6_fill4.asm
       
13 gfx4_image1.asm vykreslení rastrového obrázku získaného z binárních dat, základní varianta https://github.com/tisnik/8bit-fame/blob/master/pc-dos/gfx4_image1.asm
14 gfx4_image2.asm varianta vykreslení rastrového obrázku s využitím instrukce REP MOVSB https://github.com/tisnik/8bit-fame/blob/master/pc-dos/gfx4_image2.asm
15 gfx4_image3.asm varianta vykreslení rastrového obrázku s využitím instrukce REP MOVSW https://github.com/tisnik/8bit-fame/blob/master/pc-dos/gfx4_image3.asm
16 gfx4_image4.asm korektní vykreslení všech sudých řádků bitmapy https://github.com/tisnik/8bit-fame/blob/master/pc-dos/gfx4_image4.asm
17 gfx4_image5.asm korektní vykreslení všech sudých i lichých řádků bitmapy https://github.com/tisnik/8bit-fame/blob/master/pc-dos/gfx4_image5.asm
       
18 gfx4_image6.asm nastavení barvové palety před vykreslením obrázku https://github.com/tisnik/8bit-fame/blob/master/pc-dos/gfx4_image6.asm
19 gfx4_image7.asm nastavení barvové palety před vykreslením obrázku, snížená intenzita barev https://github.com/tisnik/8bit-fame/blob/master/pc-dos/gfx4_image7.asm
20 gfx4_image8.asm postupná změna barvy pozadí https://github.com/tisnik/8bit-fame/blob/master/pc-dos/gfx4_image8.asm
       
21 gfx6_putpixel1.asm vykreslení pixelu, základní varianta se 16bitovým násobením https://github.com/tisnik/8bit-fame/blob/master/pc-dos/gfx6_putpixel1.asm
22 gfx6_putpixel2.asm vykreslení pixelu, varianta s osmibitovým násobením https://github.com/tisnik/8bit-fame/blob/master/pc-dos/gfx6_putpixel2.asm
23 gfx6_putpixel3.asm vykreslení pixelu, varianta bez násobení https://github.com/tisnik/8bit-fame/blob/master/pc-dos/gfx6_putpixel3.asm
24 gfx6_putpixel4.asm vykreslení pixelu přes obrázek, nekorektní chování (přepis obrázku) https://github.com/tisnik/8bit-fame/blob/master/pc-dos/gfx6_putpixel4.asm
25 gfx6_putpixel5.asm vykreslení pixelu přes obrázek, korektní varianta pro bílé pixely https://github.com/tisnik/8bit-fame/blob/master/pc-dos/gfx6_putpixel5.asm
       
26 cga_text_mode1.asm standardní textový režim s rozlišením 40×25 znaků https://github.com/tisnik/8bit-fame/blob/master/pc-dos/cga_text_mode1.asm
27 cga_text_mode3.asm standardní textový režim s rozlišením 80×25 znaků https://github.com/tisnik/8bit-fame/blob/master/pc-dos/cga_text_mode3.asm
28 cga_text_mode_intensity.asm změna významu nejvyššího bitu atributového bajtu: vyšší intenzita namísto blikání https://github.com/tisnik/8bit-fame/blob/master/pc-dos/cga_text_mode_intensity.asm
29 cga_text_mode_cursor.asm změna tvaru textového kurzoru https://github.com/tisnik/8bit-fame/blob/master/pc-dos/cga_text_mode_cursor.asm
30 cga_text_gfx1.asm zobrazení „rastrové mřížky“: pseudografický režim 160×25 pixelů (interně textový režim) https://github.com/tisnik/8bit-fame/blob/master/pc-dos/cga_text_gfx1.asm
31 cga_text_mode_char_height.asm změna výšky znaků https://github.com/tisnik/8bit-fame/blob/master/pc-dos/cga_text_mode_char_height.asm
32 cga_text_160×100.asm grafický režim 160×100 se šestnácti barvami (interně upravený textový režim) https://github.com/tisnik/8bit-fame/blob/master/pc-dos/cga_text_160×100.asm
       
33 hercules_text_mode1.asm využití standardního textového režimu společně s kartou Hercules https://github.com/tisnik/8bit-fame/blob/master/pc-dos/hercules_text_mode1.asm
34 hercules_text_mode2.asm zákaz blikání v textových režimech https://github.com/tisnik/8bit-fame/blob/master/pc-dos/hercules_text_mode2.asm
35 hercules_turn_off.asm vypnutí generování video signálu https://github.com/tisnik/8bit-fame/blob/master/pc-dos/hercules_turn_off.asm
36 hercules_gfx_mode1.asm přepnutí karty Hercules do grafického režimu (základní varianta) https://github.com/tisnik/8bit-fame/blob/master/pc-dos/hercules_gfx_mode1.asm
37 hercules_gfx_mode2.asm přepnutí karty Hercules do grafického režimu (vylepšená varianta) https://github.com/tisnik/8bit-fame/blob/master/pc-dos/hercules_gfx_mode2.asm
38 hercules_putpixel.asm subrutina pro vykreslení jediného pixelu na kartě Hercules https://github.com/tisnik/8bit-fame/blob/master/pc-dos/hercules_putpixel.asm
       
39 ega_text_mode_80×25.asm standardní textový režim 80×25 znaků na kartě EGA https://github.com/tisnik/8bit-fame/blob/master/pc-dos/ega_text_mode_80×25.asm
40 ega_text_mode_80×43.asm zobrazení 43 textových řádků na kartě EGA https://github.com/tisnik/8bit-fame/blob/master/pc-dos/ega_text_mode_80×43.asm
41 ega_gfx_mode_320×200.asm přepnutí do grafického režimu 320×200 pixelů se šestnácti barvami https://github.com/tisnik/8bit-fame/blob/master/pc-dos/ega_gfx_mode_320×200.asm
42 ega_gfx_mode_640×200.asm přepnutí do grafického režimu 640×200 pixelů se šestnácti barvami https://github.com/tisnik/8bit-fame/blob/master/pc-dos/ega_gfx_mode_640×200.asm
43 ega_gfx_mode_640×350.asm přepnutí do grafického režimu 640×350 pixelů se čtyřmi nebo šestnácti barvami https://github.com/tisnik/8bit-fame/blob/master/pc-dos/ega_gfx_mode_640×350.asm
44 ega_gfx_mode_bitplanes1.asm ovládání zápisu do bitových rovin v planárních grafických režimech (základní způsob) https://github.com/tisnik/8bit-fame/blob/master/pc-dos/ega_gfx_mode_bitplanes1.asm
45 ega_gfx_mode_bitplanes2.asm ovládání zápisu do bitových rovin v planárních grafických režimech (rychlejší způsob) https://github.com/tisnik/8bit-fame/blob/master/pc-dos/ega_gfx_mode_bitplanes2.asm
       
46 ega_320×200_putpixel.asm vykreslení pixelu v grafickém režimu 320×200 pixelů se šestnácti barvami https://github.com/tisnik/8bit-fame/blob/master/pc-dos/ega_320×200_putpixel.asm
47 ega_640×350_putpixel.asm vykreslení pixelu v grafickém režimu 640×350 pixelů se šestnácti barvami https://github.com/tisnik/8bit-fame/blob/master/pc-dos/ega_640×350_putpixel.asm
       
48 ega_standard_font.asm použití standardního fontu grafické karty EGA https://github.com/tisnik/8bit-fame/blob/master/pc-dos/ega_standard_font.asm
49 ega_custom_font.asm načtení vlastního fontu s jeho zobrazením https://github.com/tisnik/8bit-fame/blob/master/pc-dos/ega_custom_font.asm
       
50 ega_palette1.asm změna barvové palety (všech 16 barev) v grafickém režimu 320×200 se šestnácti barvami https://github.com/tisnik/8bit-fame/blob/master/pc-dos/ega_palette1.asm
51 ega_palette2.asm změna barvové palety (všech 16 barev) v grafickém režimu 640×350 se šestnácti barvami https://github.com/tisnik/8bit-fame/blob/master/pc-dos/ega_palette2.asm
52 ega_palette3.asm změna všech barev v barvové paletě s využitím programové smyčky https://github.com/tisnik/8bit-fame/blob/master/pc-dos/ega_palette3.asm
53 ega_palette4.asm změna všech barev, včetně barvy okraje, v barvové paletě voláním funkce BIOSu https://github.com/tisnik/8bit-fame/blob/master/pc-dos/ega_palette4.asm

20. Odkazy na Internetu

  1. The Intel 8088 Architecture and Instruction Set
    https://people.ece.ubc.ca/~ed­c/464/lectures/lec4.pdf
  2. x86 Opcode Structure and Instruction Overview
    https://pnx.tf/files/x86_op­code_structure_and_instruc­tion_overview.pdf
  3. x86 instruction listings (Wikipedia)
    https://en.wikipedia.org/wi­ki/X86_instruction_listin­gs
  4. x86 assembly language (Wikipedia)
    https://en.wikipedia.org/wi­ki/X86_assembly_language
  5. Intel Assembler (Cheat sheet)
    http://www.jegerlehner.ch/in­tel/IntelCodeTable.pdf
  6. 25 Microchips That Shook the World
    https://spectrum.ieee.org/tech-history/silicon-revolution/25-microchips-that-shook-the-world
  7. Chip Hall of Fame: MOS Technology 6502 Microprocessor
    https://spectrum.ieee.org/tech-history/silicon-revolution/chip-hall-of-fame-mos-technology-6502-microprocessor
  8. Chip Hall of Fame: Intel 8088 Microprocessor
    https://spectrum.ieee.org/tech-history/silicon-revolution/chip-hall-of-fame-intel-8088-microprocessor
  9. Jak se zrodil procesor?
    https://www.root.cz/clanky/jak-se-zrodil-procesor/
  10. Apple II History Home
    http://apple2history.org/
  11. The 8086/8088 Primer
    https://www.stevemorse.or­g/8086/index.html
  12. flat assembler: Assembly language resources
    https://flatassembler.net/
  13. FASM na Wikipedii
    https://en.wikipedia.org/wiki/FASM
  14. Fresh IDE FASM inside
    https://fresh.flatassembler.net/
  15. MS-DOS Version 4.0 Programmer's Reference
    https://www.pcjs.org/docu­ments/books/mspl13/msdos/dos­ref40/
  16. INT 21 – DOS Function Dispatcher (DOS)
    https://www.stanislavs.or­g/helppc/int21.html
  17. DOS API (Wikipedia)
    https://en.wikipedia.org/wiki/DOS_API
  18. Bit banging
    https://en.wikipedia.org/wi­ki/Bit_banging
  19. IBM Basic assembly language and successors (Wikipedia)
    https://en.wikipedia.org/wi­ki/IBM_Basic_assembly_lan­guage_and_successors
  20. X86 Assembly/Bootloaders
    https://en.wikibooks.org/wi­ki/X86_Assembly/Bootloaders
  21. Počátky grafiky na PC: grafické karty CGA a Hercules
    https://www.root.cz/clanky/pocatky-grafiky-na-pc-graficke-karty-cga-a-hercules/
  22. Co mají společného Commodore PET/4000, BBC Micro, Amstrad CPC i grafické karty MDA, CGA a Hercules?
    https://www.root.cz/clanky/co-maji-spolecneho-commodore-pet-4000-bbc-micro-amstrad-cpc-i-graficke-karty-mda-cga-a-hercules/
  23. Karta EGA: první použitelná barevná grafika na PC
    https://www.root.cz/clanky/karta-ega-prvni-pouzitelna-barevna-grafika-na-pc/
  24. RGB Classic Games
    https://www.classicdosgames.com/
  25. Turbo Assembler (Wikipedia)
    https://en.wikipedia.org/wi­ki/Turbo_Assembler
  26. Microsoft Macro Assembler
    https://en.wikipedia.org/wi­ki/Microsoft_Macro_Assembler
  27. IBM Personal Computer (Wikipedia)
    https://en.wikipedia.org/wi­ki/IBM_Personal_Computer
  28. Intel 8251
    https://en.wikipedia.org/wi­ki/Intel_8251
  29. Intel 8253
    https://en.wikipedia.org/wi­ki/Intel_8253
  30. Intel 8255
    https://en.wikipedia.org/wi­ki/Intel_8255
  31. Intel 8257
    https://en.wikipedia.org/wi­ki/Intel_8257
  32. Intel 8259
    https://en.wikipedia.org/wi­ki/Intel_8259
  33. Support/peripheral/other chips – 6800 family
    http://www.cpu-world.com/Support/6800.html
  34. Motorola 6845
    http://en.wikipedia.org/wi­ki/Motorola_6845
  35. The 6845 Cathode Ray Tube Controller (CRTC)
    http://www.tinyvga.com/6845
  36. CRTC operation
    http://www.6502.org/users/an­dre/hwinfo/crtc/crtc.html
  37. 6845 – Motorola CRT Controller
    https://stanislavs.org/hel­ppc/6845.html
  38. The 6845 Cathode Ray Tube Controller (CRTC)
    http://www.tinyvga.com/6845
  39. Motorola 6845 and bitwise graphics
    https://retrocomputing.stac­kexchange.com/questions/10996/mo­torola-6845-and-bitwise-graphics
  40. IBM Monochrome Display Adapter
    http://en.wikipedia.org/wi­ki/Monochrome_Display_Adap­ter
  41. Color Graphics Adapter
    http://en.wikipedia.org/wi­ki/Color_Graphics_Adapter
  42. Color Graphics Adapter and the Brown color in IBM 5153 Color Display
    https://www.aceinnova.com/en/e­lectronics/cga-and-the-brown-color-in-ibm-5153-color-display/
  43. The Modern Retrocomputer: An Arduino Driven 6845 CRT Controller
    https://hackaday.com/2017/05/14/the-modern-retrocomputer-an-arduino-driven-6845-crt-controller/
  44. flat assembler: Assembly language resources
    https://flatassembler.net/
  45. FASM na Wikipedii
    https://en.wikipedia.org/wiki/FASM
  46. Fresh IDE FASM inside
    https://fresh.flatassembler.net/
  47. MS-DOS Version 4.0 Programmer's Reference
    https://www.pcjs.org/docu­ments/books/mspl13/msdos/dos­ref40/
  48. INT 21 – DOS Function Dispatcher (DOS)
    https://www.stanislavs.or­g/helppc/int21.html
  49. DOS API (Wikipedia)
    https://en.wikipedia.org/wiki/DOS_API
  50. IBM Basic assembly language and successors (Wikipedia)
    https://en.wikipedia.org/wi­ki/IBM_Basic_assembly_lan­guage_and_successors
  51. X86 Assembly/Arithmetic
    https://en.wikibooks.org/wi­ki/X86_Assembly/Arithmetic
  52. Art of Assembly – Arithmetic Instructions
    http://oopweb.com/Assembly/Do­cuments/ArtOfAssembly/Volu­me/Chapter6/CH06–2.html
  53. ASM Flags
    http://www.cavestory.org/gu­ides/csasm/guide/asm_flag­s.html
  54. Status Register
    https://en.wikipedia.org/wi­ki/Status_register
  55. Linux assemblers: A comparison of GAS and NASM
    http://www.ibm.com/develo­perworks/library/l-gas-nasm/index.html
  56. Programovani v assembleru na OS Linux
    http://www.cs.vsb.cz/gryga­rek/asm/asmlinux.html
  57. Is it worthwhile to learn x86 assembly language today?
    https://www.quora.com/Is-it-worthwhile-to-learn-x86-assembly-language-today?share=1
  58. Why Learn Assembly Language?
    http://www.codeproject.com/Ar­ticles/89460/Why-Learn-Assembly-Language
  59. Is Assembly still relevant?
    http://programmers.stackex­change.com/questions/95836/is-assembly-still-relevant
  60. Why Learning Assembly Language Is Still a Good Idea
    http://www.onlamp.com/pub/a/on­lamp/2004/05/06/writegreat­code.html
  61. Assembly language today
    http://beust.com/weblog/2004/06/23/as­sembly-language-today/
  62. Assembler: Význam assembleru dnes
    http://www.builder.cz/rubri­ky/assembler/vyznam-assembleru-dnes-155960cz
  63. Programming from the Ground Up Book – Summary
    http://savannah.nongnu.or­g/projects/pgubook/
  64. DOSBox
    https://www.dosbox.com/
  65. The C Programming Language
    https://en.wikipedia.org/wi­ki/The_C_Programming_Langu­age
  66. Hercules Graphics Card (HCG)
    https://en.wikipedia.org/wi­ki/Hercules_Graphics_Card
  67. Complete 8086 instruction set
    https://content.ctcd.edu/cou­rses/cosc2325/m22/docs/emu8086in­s.pdf
  68. Complete 8086 instruction set
    https://yassinebridi.github.io/asm-docs/8086_instruction_set.html
  69. 8088 MPH by Hornet + CRTC + DESiRE (final version)
    https://www.youtube.com/wat­ch?v=hNRO7lno_DM
  70. Area 5150 by CRTC & Hornet (Party Version) / IBM PC+CGA Demo, Hardware Capture
    https://www.youtube.com/wat­ch?v=fWDxdoRTZPc
  71. 80×86 Integer Instruction Set Timings (8088 – Pentium)
    http://aturing.umcs.maine­.edu/~meadow/courses/cos335/80×86-Integer-Instruction-Set-Clocks.pdf
  72. Colour Graphics Adapter: Notes
    https://www.seasip.info/Vin­tagePC/cga.html
  73. Restoring A Vintage CGA Card With Homebrew HASL
    https://hackaday.com/2024/06/12/res­toring-a-vintage-cga-card-with-homebrew-hasl/
  74. Demoing An 8088
    https://hackaday.com/2015/04/10/de­moing-an-8088/
  75. Video Memory Layouts
    http://www.techhelpmanual.com/89-video_memory_layouts.html
  76. Screen Attributes
    http://www.techhelpmanual.com/87-screen_attributes.html
  77. IBM PC Family – BIOS Video Modes
    https://www.minuszerodegre­es.net/video/bios_video_mo­des.htm
  78. EGA Functions
    https://cosmodoc.org/topics/ega-functions/#the-hierarchy-of-the-ega
  79. Why the EGA can only use 16 of its 64 colours in 200-line modes
    https://www.reenigne.org/blog/why-the-ega-can-only-use-16-of-its-64-colours-in-200-line-modes/
  80. How 16 colors saved PC gaming – the story of EGA graphics
    https://www.custompc.com/retro-tech/ega-graphics
  81. List of 16-bit computer color palettes
    https://en.wikipedia.org/wi­ki/List_of16-bit_computer_color_palettes
ikonka

Zajímá vás toto téma? Chcete se o něm dozvědět víc?

Objednejte si upozornění na nově vydané články do vašeho mailu. Žádný článek vám tak neuteče.

Byl pro vás článek přínosný?

Autor článku

Vystudoval VUT FIT a v současné době pracuje na projektech vytvářených v jazycích Python a Go.