Hlavní navigace

Skrytá síla karty VGA: čtecí a zápisové režimy (dokončení)

10. 9. 2024
Doba čtení: 54 minut

Sdílet

 Autor: Pavel Tišnovský
Dnes dokončíme popis možností grafické karty VGA. Ukážeme si, jaké operace lze provádět při čtení a při zápisu do obrazové paměti, a to včetně popisu rychlé operace blokového přenosu (BitBLT), kdy lze přenést celých 32 bitů.

Obsah

1. Skrytá síla karty VGA: čtecí a zápisové režimy (dokončení)

2. Bitová rotace při zápisu hodnot do video paměti

3. Úplný zdrojový kód dnešního prvního demonstračního příkladu

4. Vizuální ukázka postupné bitové rotace

5. Využití záchytného registru při blokových přenosech

6. Volba zápisového režimu a blokový přenos po 32 bitech

7. Úplný zdrojový kód dnešního druhého demonstračního příkladu

8. Využití záchytného registru v režimech s 256 barvami

9. Přenos obrázku z horní poloviny obrazovky do dolní poloviny v 256barevném režimu

10. Blokový přenos v 256barevném nezřetězeném režimu bez přímého využití latche

11. Výsledky blokového přenosu

12. Blokový přenos v 256barevném nezřetězeném režimu s využitím latche

13. Výsledky blokového přenosu

14. Logické operace prováděné při zápisu do obrazové paměti

15. Vyplnění části obrazovky s volitelnou aplikací logické operace

16. Vyplnění části obrazovky konstantní barvou při zákazu logických operací

17. Obnova obsahu latche před každým zápisem

18. Nastavení logické operace prováděné při zápisu do obrazové paměti

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

20. Odkazy na Internetu

1. Skrytá síla karty VGA: čtecí a zápisové režimy (dokončení)

V dnešním článku dokončíme popis programování grafické karty VGA. Ukážeme si, jaké zbylé operace je možné provádět při čtení, resp. při zápisu do obrazové paměti – protože mezi mikroprocesorem a video pamětí leží nejenom (pomalá) sběrnice, ale i několik obvodů na řadiči VGA, které dokážou provádět logické operace, bitové operace, rozkopírování dat do bitových rovin, ale například i zápis hodnot pixelů z takzvaného záchytného registru (latche). Tyto operace se řídí pomocí registrů grafického řadiče dostupného na I/O portu 0×3ce a 0×3cf (volba registru a zápis či čtení informace do/z registru):

Index Název Stručný popis
00 Set/Reset hodnoty bitů v tomto registru se mohou zapsat do bitových rovin (bez ohledu na zapisovaná data)
01 Enable Set/Reset volba, zda se při zápisu mají použít zapisovaná data nebo bity z předchozího registru
02 Color Compare barva 0–15 použitá ve čtecím režimu číslo 1
03 Data Rotate volba logické operace a rotace bitů (viz další text)
04 Read Map Select volba bitové roviny pro operaci čtení (již známe)
05 Graphics Mode volba čtecích a zápisových režimů, přepnutí do režimu s 256 barvami atd.
06 Miscellaneous Graphics volba adresování video paměti, režimu sudá-lichá atd.
07 Color Don't Care barva 0–15 použitá ve čtecím režimu číslo
08 Bit Mask bitová maska při zápisu (platí pro všechny bitové roviny)

Zajímavá je kombinace prvních dvou registrů, protože s jejich využitím lze zajistit „kolmý režim“ zápisu. Barva se zapíše do prvního registru (0–15), druhý registr se nastaví na hodnotu 15 a poté lze jedním zápisem (libovolné hodnoty) nastavit barvu sousedních pixelů. Popř. lze ještě použít poslední registr BitMask pro maskování, které pixely se mají změnit. Základní způsob použití lze otestovat na příkladu vga_set_reset.asm.

Poznámka: na tomto místě je vhodné upozornit na to, že většina operací (logické operace, bitové rotace, maskování atd.) počítá s tím, že čtení či zápis dat do operační paměti je prováděn po bajtech, nikoli po šestnáctibitových slovech. Do určité míry se jedná o dědictví původní osmibitové směrnice počítačů IBM PC, i když VGA byla typicky připojena na šestnáctibitovou sběrnici ISA.

2. Bitová rotace při zápisu hodnot do video paměti

První operací, kterou si dnes popíšeme, je bitová rotace prováděná při zápisu hodnot do video paměti. Bajty (nikoli celá slova) se totiž před zápisem do video paměti podrobují logickým operacím, které si vysvětlíme dále, a taktéž rotaci o 0 až 7 bitů. Obě tyto operace se konfigurují v řídicím registru nazvaném DATA ROTATE, který má následující strukturu:

+---+---+---+---+---+---+---+---+
| 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
+---+---+---+---+---+---+---+---+
|   |   |   |logická|  bitová   |
|   |   |   |operace|  rotace   |
+---+---+---+---+---+---+---+---+

Pro zápis hodnot do tohoto řídicího registru grafické karty VGA použijeme toto makro:

; nastaveni logickeho rezimu pri zapisu
%macro write_bit_rotate 1
        mov  dx, GRAPHICS_REGISTER
        mov  al, DATA_ROTATE
        out  dx, al         ; vyber VGA registru pro zapis
        inc  dx,
        mov  al, %1         ; zmena VGA registru
        out  dx, al
%endmacro

V demonstračním příkladu budeme provádět operaci BitBLT (tedy blokový přenos) z první poloviny obrazovky do druhé poloviny (obrazovka je vyplněna barevnými úsečkami). Přitom budeme postupně měnit počet rotovaných bitů od 0 (výchozí hodnota) do sedmi. Pro zajímavost použijeme jako počitadlo smyčky osmibitový pracovní registr AH, i když se typicky používá CX nebo pro osmibitové operace CL:

        mov ah, 0
.rotate:
        push ax
        write_bit_rotate ah   ; rotace bitu pri zapisu do bitovych rovin
        call bitblt           ; prenos bloku
        wait_key              ; cekani na klavesu
        pop ax
        inc ah
        cmp ah, 8
        jne .rotate

3. Úplný zdrojový kód dnešního prvního demonstračního příkladu

Úplný zdrojový kód dnešního prvního demonstračního příkladu, který při blokovém přenosu provádí bitové rotace bajtů zapisovaných do video paměti, vypadá následovně:

; Graficky rezim karty VGA s rozlisenim 640x480 pixelu.
; Zmena barvovych rovin, do kterych se zapisuje.
; Vykresleni barevnych usecek.
; Prenos casti obrazu operaci typu BitBLT - nyni jiz korektni.
; Vyber bitovych rovin pro zapis.
; Vyber bitove roviny pro cteni.
; Rotace bitu pri zapisu.
;
; preklad pomoci:
;     nasm -f bin -o vga.com vga_bitblt_rotate.asm
;
; nebo pouze:
;     nasm -o vga.com vga_bitblt_rotate.asm
 
 
;-----------------------------------------------------------------------------
 
; I/O porty karty EGA/VGA
GRAPHICS_REGISTER    equ 0x3ce
SEQUENCER_INDEX      equ 0x3c4
SEQUENCER_DATA       equ 0x3c5
 
; registry karty EGA/VGA
BITPLANE_SELECTOR    equ 0x02   ; sequencer
DATA_ROTATE          equ 0x03   ; graphics register
READ_MAP_SELECT      equ 0x04   ; graphics register
 
 
 
; 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
 
; vyber bitove roviny nebo bitovych rovin pro zapis
%macro select_bitplanes_for_write 1
        mov  al, %1         ; bitova rovina
        mov  dx, SEQUENCER_INDEX
        mov  ah, BITPLANE_SELECTOR
        xchg ah, al
        out  dx, ax         ; vyber registru sekvenceru
                            ; a zapis masky bitovych rovin
%endmacro
 
; vyber bitove roviny pro cteni
%macro select_bitplane_for_read 1
        mov  dx, GRAPHICS_REGISTER
        mov  al, READ_MAP_SELECT
        out  dx, al         ; vyber VGA registru pro zapis
        inc  dx,
        mov  al, %1         ; zmena VGA registru
        out  dx, al
%endmacro
 
; nastaveni logickeho rezimu pri zapisu
%macro write_bit_rotate 1
        mov  dx, GRAPHICS_REGISTER
        mov  al, DATA_ROTATE
        out  dx, al         ; vyber VGA registru pro zapis
        inc  dx,
        mov  al, %1         ; zmena VGA registru
        out  dx, al
%endmacro
 
;-----------------------------------------------------------------------------
org  0x100        ; zacatek kodu pro programy typu COM (vzdy se zacina na 256)
 
start:
        gfx_mode 0x12         ; nastaveni rezimu 640x480 se sestnacti barvami
        call draw_color_lines
        wait_key              ; cekani na klavesu
 
        mov ah, 0
.rotate:
        push ax
        write_bit_rotate ah   ; rotace bitu pri zapisu do bitovych rovin
        call bitblt           ; prenos bloku
        wait_key              ; cekani na klavesu
        pop ax
        inc ah
        cmp ah, 8
        jne .rotate
 
        exit                  ; navrat do DOSu
 
 
; operace BitBLT z prvni poloviny obrazovky na druhou polovinu
bitblt:
        mov ax, 0xa000      ; video RAM v textovem rezimu
        mov es, ax
        mov ds, ax
 
        mov  bx, .regs      ; tabulka s mapovanim cteni->zapis
        mov  cx, 4          ; pocet bitovych rovin pro prenos
 
.all_bitplanes:
        mov  dx, GRAPHICS_REGISTER
        mov  al, READ_MAP_SELECT
        mov  ah, cs:[bx]    ; nacteni indexu bitove roviny
        inc  bx             ; posun v tabulce
        out  dx, ax         ; vyber bitove roviny pro cteni
 
        mov  dx, SEQUENCER_INDEX
        mov  al, BITPLANE_SELECTOR
        mov  ah, cs:[bx]    ; vyber bitovych rovin pro zapis
        inc  bx             ; posun v tabulce
        out  dx, ax         ; vyber registru sekvenceru
                            ; a zapis masky bitovych rovin
 
        push cx
        call bitblt_one_bitplane
        pop cx
        loop .all_bitplanes
        ret
 
.regs:  db 0, 1, 1, 2, 2, 4, 3, 8
 
bitblt_one_bitplane:
        mov di, 640*240/8   ; nyni ES:DI obsahuje adresu pixelu ve video RAM na 240 radku
        xor si, si          ; nyni DS:SI obsahuje adresu prvniho pixelu ve video RAM
 
        mov cx, 640*240/8   ; pocet prenesenych bajtu
        rep movsb           ; blokovy prenos po bajtech
        ret                 ; hotovo
 
 
draw_color_lines:
        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, 15          ; barva
        call putpixel       ; vykreslení pixelu
        pop ax
 
        push ax
        mov cl,  7          ; barva
        add ax, 10          ; horizontalni posun usecky
        call putpixel       ; vykreslení pixelu
        pop ax
 
        push ax
        mov cl,  1          ; barva
        add ax, 20          ; horizontalni posun usecky
        call putpixel       ; vykreslení pixelu
        pop ax
 
        push ax
        mov cl,  2          ; barva
        add ax, 30          ; horizontalni posun usecky
        call putpixel       ; vykreslení pixelu
        pop ax
 
        push ax
        mov cl,  4          ; barva
        add ax, 40          ; horizontalni posun usecky
        call putpixel       ; vykreslení pixelu
        pop ax
 
        inc ax              ; pusun x+=1, y+=1
        cmp ax, 480         ; hranice obrazovky?
        jne .opak           ; ne-opakujeme
        ret                 ; hotovo
 
 
; Vykresleni pixelu
; AX - x-ova souradnice
; BX - y-ova souradnice
; CL - barva
putpixel:
        push ax
        mov al, cl         ; vyber bitove roviny nebo bitovych rovin
        select_bitplanes_for_write al
        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                ; hotovo

4. Vizuální ukázka postupné bitové rotace

Podívejme se nyní, jak vlastně bitová rotace zapisovaných bajtů vypadá v praxi. Pro rotaci 0 až 7 bitů vypadají výsledné obsahy obrazovek následovně:

vga-bitblt-a-1

Obrázek 1: Původní obrázek, prozatím bez provedení blokového přenosu.

vga-bitblt-a-2

Obrázek 2: Přenos s bitovou rotací o 0 bitů (tedy bez rotace).

vga-bitblt-a-3

Obrázek 3: Přenos s bitovou rotací o 1 bit.

vga-bitblt-a-4

Obrázek 4: Přenos s bitovou rotací o 2 bity.

vga-bitblt-a-5

Obrázek 5: Přenos s bitovou rotací o 3 bity.

vga-bitblt-a-6

Obrázek 6: Přenos s bitovou rotací o 4 bity.

vga-bitblt-a-7

Obrázek 7: Přenos s bitovou rotací o 5 bitů.

vga-bitblt-a-8

Obrázek 8: Přenos s bitovou rotací o 6 bitů.

vga-bitblt-a-9

Obrázek 9: Přenos s bitovou rotací o 7 bitů.

5. Využití záchytného registru při blokových přenosech

Poměrně často se setkáme s nutností přenosu větších bloků dat do viditelné části obrazové paměti. Příkladem může být kurzor myši, ale například i postavy nebo další pohybující se předměty ve hrách. Ovšem grafická karta VGA neobsahuje specializovaný obvod pro blokové přenosy, takže je nutné je realizovat programově („ručně“). Nabízí se dvě řešení. První z těchto řešení spočívá v tom, že se obrazová data (bloky) budou přenášet z operační paměti přes relativně pomalou sběrnici VGA.

A druhá varianta spočívá v tom, že si tyto bloky uložíme do neviditelné části obrazové paměti a přenos bude prováděn z jedná oblasti obrazové paměti do oblasti jiné. To, jak využijeme neviditelnou část obrazové paměti, totiž záleží čistě na nás – může se jednat o druhý či třetí zadní buffer, buffer pro grafické bloky – sprity atd.

I z tohoto důvodu je v grafické kartě VGA implementován takzvaný záchytný registr neboli latch, který má šířku 32 bitů. Při čtení z video RAM se – nezávisle na vybrané bitové rovině – do latche přečte obsah všech čtyř bitových rovin, konkrétně z každé roviny jeden bajt. A při zápisu lze zvolit takový režim, že se bude ignorovat bajt poslaný z CPU a namísto něho se využije oněch 32 bitů z latche. Výsledkem je, že i když se fyzicky bude přenášet jen jediný bajt, interně karta VGA přenese 32 bitů a tedy zkopíruje osm pixelů (16barevné režimy) nebo čtyři pixely (256barevné režimy). Tímto konceptem, jenž se uplatnil při vykreslování spritů atd., se budeme v této části článku.

6. Volba zápisového režimu a blokový přenos po 32 bitech

Činnost záchytného registru při blokových přenosech lze popsat následovně:

  1. Při čtení (bajtu!) z předem zvolené bitové roviny se ve skutečnosti přečtou čtyři bajty, z každé bitové roviny jeden.
  2. Všechny čtyři přečtené bajty se zapíšou do záchytného registru (latche).
  3. CPU získá pouze hodnotu bajtu z vybrané bitové roviny (to již známe).
  4. Pokud je zvolen zápisový režim číslo 2, bude se zapisovaný bajt ignorovat a ve skutečnosti se do všech čtyř bitových rovin zapíšou bajty uložené dolatche – zapíše se tedy celých 32 bitů.
Poznámka: to vlastně znamená, že při tomto blokovém přenosu mají pro VGA význam pouze adresy pro čtení a zápis a i osmibitové přenosy (z hlediska CPU) znamenají 32bitové přenosy v rámci obrazové paměti (tedy osm pixelů v 16barevném režimu a čtyři pixely v režimu 256barevném).

Volbu zápisového režimu provedeme tímto pomocným makrem:

; nastaveni zapisoveho rezimu
%macro write_mode 1
        mov  dx, GRAPHICS_REGISTER
        mov  al, GRAPHICS_MODE
        out  dx, al         ; vyber VGA registru pro zapis
        inc  dx,
        mov  al, %1         ; zmena VGA registru
        out  dx, al
%endmacro

Zápisový režim číslo 2 se volí následovně:

write_mode 0b00000001 ; zapisovy rezim cislo 2
call bitblt           ; prenos bloku

Nakonec samotná realizace blokového přenosu (polovina obrazovky) pracuje jen s jednou bitovou rovinou (z pohledu CPU):

; operace BitBLT z prvni poloviny obrazovky na druhou polovinu
bitblt:
        mov ax, 0xa000      ; video RAM v textovem rezimu
        mov es, ax
        mov ds, ax
 
        mov di, 640*240/8   ; nyni ES:DI obsahuje adresu pixelu ve video RAM na 240 radku
        xor si, si          ; nyni DS:SI obsahuje adresu prvniho pixelu ve video RAM
 
        mov cx, 640*240/8   ; pocet prenesenych bajtu
        rep movsb           ; blokovy prenos po bajtech
        ret                 ; hotovo

Výsledky odpovídají očekávání:

vga-bitblt-a-10

Obrázek 10: Obrazovka před provedením blokového přenosu.

vga-bitblt-a-11

Obrázek 11: Obrazovka po provedení blokového přenosu.

7. Úplný zdrojový kód dnešního druhého demonstračního příkladu

Úplná podoba dnešního druhého demonstračního příkladu s implementací rychlé operace typu BitBLT vypadá následovně:

; Graficky rezim karty VGA s rozlisenim 640x480 pixelu.
; Zmena barvovych rovin, do kterych se zapisuje.
; Vykresleni barevnych usecek.
; Prenos casti obrazu operaci typu BitBLT - nyni jiz korektni.
; Pro prenos dat se pouziva 32bitovy latch.
;
; preklad pomoci:
;     nasm -f bin -o vga.com vga_bitblt_fast.asm
;
; nebo pouze:
;     nasm -o vga.com vga_bitblt_fast.asm
 
 
;-----------------------------------------------------------------------------
 
; I/O porty karty EGA/VGA
GRAPHICS_REGISTER    equ 0x3ce
SEQUENCER_INDEX      equ 0x3c4
SEQUENCER_DATA       equ 0x3c5
 
; registry karty EGA/VGA
BITPLANE_SELECTOR    equ 0x02   ; sequencer
GRAPHICS_MODE        equ 0x05   ; graphics register
READ_MAP_SELECT      equ 0x04   ; graphics register
 
 
; 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
 
; vyber bitove roviny nebo bitovych rovin pro zapis
%macro select_bitplanes_for_write 1
        mov  al, %1         ; bitova rovina
        mov  dx, SEQUENCER_INDEX
        mov  ah, BITPLANE_SELECTOR
        xchg ah, al
        out  dx, ax         ; vyber registru sekvenceru
                            ; a zapis masky bitovych rovin
%endmacro
 
; vyber bitove roviny pro cteni
%macro select_bitplane_for_read 1
        mov  dx, GRAPHICS_REGISTER
        mov  al, READ_MAP_SELECT
        out  dx, al         ; vyber VGA registru pro zapis
        inc  dx,
        mov  al, %1         ; zmena VGA registru
        out  dx, al
%endmacro
 
; nastaveni zapisoveho rezimu
%macro write_mode 1
        mov  dx, GRAPHICS_REGISTER
        mov  al, GRAPHICS_MODE
        out  dx, al         ; vyber VGA registru pro zapis
        inc  dx,
        mov  al, %1         ; zmena VGA registru
        out  dx, al
%endmacro
 
;-----------------------------------------------------------------------------
org  0x100        ; zacatek kodu pro programy typu COM (vzdy se zacina na 256)
 
start:
        gfx_mode 0x12         ; nastaveni rezimu 640x480 se sestnacti barvami
        call draw_color_lines
        select_bitplanes_for_write 15
        wait_key              ; cekani na klavesu
 
        write_mode 0b00000001 ; zapisovy rezim cislo 2
        call bitblt           ; prenos bloku
        wait_key              ; cekani na klavesu
 
        exit                  ; navrat do DOSu
 
 
; operace BitBLT z prvni poloviny obrazovky na druhou polovinu
bitblt:
        mov ax, 0xa000      ; video RAM v textovem rezimu
        mov es, ax
        mov ds, ax
 
        mov di, 640*240/8   ; nyni ES:DI obsahuje adresu pixelu ve video RAM na 240 radku
        xor si, si          ; nyni DS:SI obsahuje adresu prvniho pixelu ve video RAM
 
        mov cx, 640*240/8   ; pocet prenesenych bajtu
        rep movsb           ; blokovy prenos po bajtech
        ret                 ; hotovo
 
 
draw_color_lines:
        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, 15          ; barva
        call putpixel       ; vykreslení pixelu
        pop ax
 
        push ax
        mov cl,  7          ; barva
        add ax, 10          ; horizontalni posun usecky
        call putpixel       ; vykreslení pixelu
        pop ax
 
        push ax
        mov cl,  1          ; barva
        add ax, 20          ; horizontalni posun usecky
        call putpixel       ; vykreslení pixelu
        pop ax
 
        push ax
        mov cl,  2          ; barva
        add ax, 30          ; horizontalni posun usecky
        call putpixel       ; vykreslení pixelu
        pop ax
 
        push ax
        mov cl,  4          ; barva
        add ax, 40          ; horizontalni posun usecky
        call putpixel       ; vykreslení pixelu
        pop ax
 
        inc ax              ; pusun x+=1, y+=1
        cmp ax, 480         ; hranice obrazovky?
        jne .opak           ; ne-opakujeme
        ret                 ; hotovo
 
 
; Vykresleni pixelu
; AX - x-ova souradnice
; BX - y-ova souradnice
; CL - barva
putpixel:
        push ax
        mov al, cl         ; vyber bitove roviny nebo bitovych rovin
        select_bitplanes_for_write al
        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                ; hotovo

8. Využití záchytného registru v režimech s 256 barvami

V šestnáctibarevných režimech je záchytný registr použit přesně tak, jak to bylo popsáno v předchozím textu, a umožňuje nám tak přenášet jedinou operací osm sousedních pixelů. V režimech s 256 barvami je situace obdobná, ovšem kvůli odlišné organizaci video paměti se na celou operaci můžeme dívat nepatrně jiným způsobem:

  1. Při čtení se z každé bitové roviny přečte barva jednoho pixelu. Všechny čtyři přečtené barvy se uloží do latche.
  2. Při zápisu se čtyři barvy z latche zapíšou do jednotlivých bitových rovin.

Způsob provedené blokové operace s nezřetězených 256 režimech si ukážeme v navazujících kapitolách (ve zřetězeném režimu 13h postrádá význam, protože vždy 3 bajty jsou nevyužity).

9. Přenos obrázku z horní poloviny obrazovky do dolní poloviny v 256barevném režimu

Samotná realizace blokového přenosu rastrového obrázku z horní poloviny obrazovky do dolní poloviny v režimech s 256 barvami a s nezřetězenými rovinami může vypadat následovně. Povšimněte si, že s obrazovou pamětí pracujeme, jakoby nebyla rozdělena na bitové roviny, takže se výsledky přenosu budou odlišovat podle toho, jestli využijeme latch (tedy zápisový režim 2) nebo nikoli. Subrutina je upravena pro grafický režim s rozlišením 320×400 pixelů:

; operace BitBLT z prvni poloviny obrazovky na druhou polovinu
bitblt:
        mov ax, 0xa000      ; video RAM v textovem rezimu
        mov es, ax
        mov ds, ax
 
        mov di, 320*200/4   ; nyni ES:DI obsahuje adresu pixelu ve video RAM na 200 radku
        xor si, si          ; nyni DS:SI obsahuje adresu prvniho pixelu ve video RAM
 
        mov cx, 320*200/4   ; pocet prenesenych bajtu
        rep movsb           ; blokovy prenos po bajtech
        ret                 ; hotovo

10. Blokový přenos v 256barevném nezřetězeném režimu bez přímého využití latche

Nejprve se pokusíme o blokový přenos rastrového obrázku v režimu 320×400 při použití zápisového režimu číslo 0, tedy režimu, v němž je nutné vybrat bitovou rovinu (nebo bitové roviny) pro zápis. Před zavoláním subrutiny bitblt nastavíme všechny čtyři bitové roviny pro zápis, takže se každý přečtený pixel rozkopíruje do všech čtyř rovin (a vlastně se tak 4× sníží horizontální rozlišení):

        select_bitplane 15  ; vyber vsech bitovych rovin
        call bitblt         ; prenos bloku

A takto vypadá úplný zdrojový kód tohoto demonstračního příkladu:

; Graficky rezim karty VGA s rozlisenim 320x400 pixelu.
; Vypnuti zretezeni bitovych rovin.
; Vykresleni rastroveho obrazku postupne do vsech bitovych rovin.
; Bitovy prenos (nedokonceny).
;
; preklad pomoci:
;     nasm -f bin -o vga.com vga_320x400_bitblt_1.asm
;
; nebo pouze:
;     nasm -o vga.com vga_320x400_bitblt_1.asm
 
 
;-----------------------------------------------------------------------------
 
; registry karty VGA
SEQUENCER_INDEX      equ 0x3c4
SEQUENCER_DATA       equ 0x3c5
CRTC_INDEX           equ 0x3d4
CRTC_DATA            equ 0x3d5
BITPLANE_SELECTOR    equ 0x02
MEMORY_MODE_REGISTER equ 0x04   ; sekvencer
UNDERLINE_LOCATION   equ 0x14   ; CRTC
MODE_CONTROL         equ 0x17   ; CRTC
MAXIMUM_SCAN_LINE    equ 0x09   ; CRTC
 
; 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
 
; nastaveni jednoho registru sekvenceru
%macro set_sequencer_register 2
        mov dx, SEQUENCER_INDEX
        mov al, %1    ; ridici registr
        out dx, al
        inc dx
        mov al, %2    ; hodnota zapisovana do registru
        out dx, al
%endmacro
 
; nastaveni jednoho CRTC registru
%macro set_crtc_register 2
        mov dx, CRTC_INDEX
        mov al, %1    ; ridici registr (CRTC)
        out dx, al
        inc dx
        mov al, %2    ; hodnota zapisovana do registru
        out dx, al
%endmacro
 
; vyber bitove roviny
%macro select_bitplane 1
        mov  al, %1         ; bitova rovina
        mov  dx, SEQUENCER_INDEX
        mov  ah, BITPLANE_SELECTOR
        xchg ah, al
        out  dx, ax         ; vyber registru sekvenceru
                            ; a zapis masky bitovych rovin
%endmacro
 
; paleta ve stupnich sedi
%macro grayscale_palette 0
        mov ax, 0x1010      ; cislo sluzby a podsluzby VGA BIOSu
        xor bl, bl          ; index barvy
next_dac:
        mov ch, bl          ; prvni barvova slozka
        shr ch, 1
        shr ch, 1
        mov cl, ch          ; druha barvova slozka
        mov dh, ch          ; treti barvova slozka
        int 0x10            ; modifikace mapovani v DAC
        inc bl              ; zvysit index v DAC
        jnz next_dac        ; nastavit dalsi barvu, dokud nedosahneme hodnoty 256
%endmacro
 
;-----------------------------------------------------------------------------
org  0x100        ; zacatek kodu pro programy typu COM (vzdy se zacina na 256)
 
start:
        gfx_mode 0x13       ; nastaveni rezimu 320x200 s 256 barvami
        grayscale_palette   ; nastaveni palety se stupni sedi
 
                            ; mod 320x200 bez zretezeni rovin
        set_sequencer_register MEMORY_MODE_REGISTER, 0x06 ; vypnuti zretezeni + povoleni 256 kB RAM
        set_crtc_register UNDERLINE_LOCATION, 0x00        ; vypnuti double word rezimu
        set_crtc_register MODE_CONTROL,  0xe3             ; zapnuti bytoveho rezimu
        set_crtc_register MAXIMUM_SCAN_LINE, 0x40         ; 400 grafickych radku
 
        mov ax, cs
        mov ds, ax          ; zajistit, ze bude mozne adresovat cely obrazek
 
        mov ax, 0xa000      ; video RAM v textovem rezimu
        mov es, ax
 
        select_bitplane 1   ; prvni bitplane
        xor ax, ax          ; offset pixelu
        call move_image_part; prenest obrazek
 
        select_bitplane 2   ; druha bitplane
        mov ax, 1
        call move_image_part; prenest obrazek
 
        select_bitplane 4   ; treti bitplane
        mov ax, 2
        call move_image_part; prenest obrazek
 
        select_bitplane 8   ; ctvrta bitplane
        mov ax, 3
        call move_image_part; prenest obrazek
 
        wait_key            ; cekani na klavesu
 
        select_bitplane 15  ; vyber vsech bitovych rovin
        call bitblt         ; prenos bloku
        wait_key            ; cekani na klavesu
 
        exit                ; navrat do DOSu
 
 
; operace BitBLT z prvni poloviny obrazovky na druhou polovinu
bitblt:
        mov ax, 0xa000      ; video RAM v textovem rezimu
        mov es, ax
        mov ds, ax
 
        mov di, 320*200/4   ; nyni ES:DI obsahuje adresu pixelu ve video RAM na 200 radku
        xor si, si          ; nyni DS:SI obsahuje adresu prvniho pixelu ve video RAM
 
        mov cx, 320*200/4   ; pocet prenesenych bajtu
        rep movsb           ; blokovy prenos po bajtech
        ret                 ; hotovo
 
move_image_part:
        mov si, image       ; nyni DS:SI obsahuje adresu prvniho bajtu v obrazku
        add si, ax          ; offset pixelu
        xor di, di          ; nyni ES:DI obsahuje adresu prvniho pixelu ve video RAM
 
        mov cx, 320*200/4   ; pocet zapisovanych bajtu (=pixelu)
.block_move:
        lodsb               ; nacist bajt z obrazku
        add si, 3           ; celkove posun o 4 pixely v obrazku 
        stosb               ; ulozit do obrazove pameti
        loop .block_move    ; presunout CX pixelu
        ret
 
; pridani binarnich dat s rastrovym obrazkem
image:
    incbin "image_320x200.bin"

11. Výsledky blokového přenosu

Podívejme se nyní na výsledky blokového přenosu realizovaného příkladem z předchozí kapitoly:

vga-bitblt-b-1

Obrázek 12: Obrazovka před provedením blokového přenosu obrázku.

vga-bitblt-b-2

Obrázek 13: Obrazovka po provedení blokového přenosu obrázku.

Ze zobrazených výsledků je zřejmé, že se skutečně přečetla jen čtvrtina pixelů, ovšem díky zápisu do všech čtyř bitových rovin se hodnoty každého pixelu zapsaly i do trojice pixelů sousedních (mimochodem: podobný způsob je realizován i v původní hře Doom, pokud se přepnete do režimu s nižším rozlišením).

12. Blokový přenos v 256barevném nezřetězeném režimu s využitím latche

Nyní předchozí demonstrační příklad nepatrně upravíme, a to konkrétně takovým způsobem, že před blokovým přenosem rastrového obrázku nastavíme zápisový režim číslo 2. Současně stále musíme povolit zápis do všech bitových rovin (zkuste si tuto část změnit a uvidíte proč):

        select_bitplane 15  ; vyber vsech bitovych rovin
        write_mode 0b01000001 ; zapisovy rezim cislo 2
        call bitblt           ; prenos bloku

Opět se podívejme na úplný zdrojový kód takto upraveného příkladu:

; Graficky rezim karty VGA s rozlisenim 320x400 pixelu.
; Vypnuti zretezeni bitovych rovin.
; Vykresleni rastroveho obrazku postupne do vsech bitovych rovin.
; Bitovy prenos (dokonceny).
;
; preklad pomoci:
;     nasm -f bin -o vga.com vga_320x400_bitblt_2.asm
;
; nebo pouze:
;     nasm -o vga.com vga_320x400_bitblt_2.asm
 
 
;-----------------------------------------------------------------------------
 
; registry karty VGA
SEQUENCER_INDEX      equ 0x3c4
SEQUENCER_DATA       equ 0x3c5
CRTC_INDEX           equ 0x3d4
CRTC_DATA            equ 0x3d5
GRAPHICS_REGISTER    equ 0x3ce
BITPLANE_SELECTOR    equ 0x02
GRAPHICS_MODE        equ 0x05   ; graphics register
READ_MAP_SELECT      equ 0x04   ; graphics register
MEMORY_MODE_REGISTER equ 0x04   ; sekvencer
UNDERLINE_LOCATION   equ 0x14   ; CRTC
MODE_CONTROL         equ 0x17   ; CRTC
MAXIMUM_SCAN_LINE    equ 0x09   ; CRTC
 
; 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
 
; nastaveni jednoho registru sekvenceru
%macro set_sequencer_register 2
        mov dx, SEQUENCER_INDEX
        mov al, %1    ; ridici registr
        out dx, al
        inc dx
        mov al, %2    ; hodnota zapisovana do registru
        out dx, al
%endmacro
 
; nastaveni jednoho CRTC registru
%macro set_crtc_register 2
        mov dx, CRTC_INDEX
        mov al, %1    ; ridici registr (CRTC)
        out dx, al
        inc dx
        mov al, %2    ; hodnota zapisovana do registru
        out dx, al
%endmacro
 
; vyber bitove roviny
%macro select_bitplane 1
        mov  al, %1         ; bitova rovina
        mov  dx, SEQUENCER_INDEX
        mov  ah, BITPLANE_SELECTOR
        xchg ah, al
        out  dx, ax         ; vyber registru sekvenceru
                            ; a zapis masky bitovych rovin
%endmacro
 
; paleta ve stupnich sedi
%macro grayscale_palette 0
        mov ax, 0x1010      ; cislo sluzby a podsluzby VGA BIOSu
        xor bl, bl          ; index barvy
next_dac:
        mov ch, bl          ; prvni barvova slozka
        shr ch, 1
        shr ch, 1
        mov cl, ch          ; druha barvova slozka
        mov dh, ch          ; treti barvova slozka
        int 0x10            ; modifikace mapovani v DAC
        inc bl              ; zvysit index v DAC
        jnz next_dac        ; nastavit dalsi barvu, dokud nedosahneme hodnoty 256
%endmacro
 
; nastaveni zapisoveho rezimu
%macro write_mode 1
        mov  dx, GRAPHICS_REGISTER
        mov  al, GRAPHICS_MODE
        out  dx, al         ; vyber VGA registru pro zapis
        inc  dx,
        mov  al, %1         ; zmena VGA registru
        out  dx, al
%endmacro
 
;-----------------------------------------------------------------------------
org  0x100        ; zacatek kodu pro programy typu COM (vzdy se zacina na 256)
 
start:
        gfx_mode 0x13       ; nastaveni rezimu 320x200 s 256 barvami
        grayscale_palette   ; nastaveni palety se stupni sedi
 
                            ; mod 320x200 bez zretezeni rovin
        set_sequencer_register MEMORY_MODE_REGISTER, 0x06 ; vypnuti zretezeni + povoleni 256 kB RAM
        set_crtc_register UNDERLINE_LOCATION, 0x00        ; vypnuti double word rezimu
        set_crtc_register MODE_CONTROL,  0xe3             ; zapnuti bytoveho rezimu
        set_crtc_register MAXIMUM_SCAN_LINE, 0x40         ; 400 grafickych radku
 
        mov ax, cs
        mov ds, ax          ; zajistit, ze bude mozne adresovat cely obrazek
 
        mov ax, 0xa000      ; video RAM v textovem rezimu
        mov es, ax
 
        select_bitplane 1   ; prvni bitplane
        xor ax, ax          ; offset pixelu
        call move_image_part; prenest obrazek
 
        select_bitplane 2   ; druha bitplane
        mov ax, 1
        call move_image_part; prenest obrazek
 
        select_bitplane 4   ; treti bitplane
        mov ax, 2
        call move_image_part; prenest obrazek
 
        select_bitplane 8   ; ctvrta bitplane
        mov ax, 3
        call move_image_part; prenest obrazek
 
        wait_key            ; cekani na klavesu
 
        select_bitplane 15  ; vyber vsech bitovych rovin
        write_mode 0b01000001 ; zapisovy rezim cislo 2
        call bitblt         ; prenos bloku
        wait_key            ; cekani na klavesu
 
        exit                ; navrat do DOSu
 
 
; operace BitBLT z prvni poloviny obrazovky na druhou polovinu
bitblt:
        mov ax, 0xa000      ; video RAM v textovem rezimu
        mov es, ax
        mov ds, ax
 
        mov di, 320*200/4   ; nyni ES:DI obsahuje adresu pixelu ve video RAM na 200 radku
        xor si, si          ; nyni DS:SI obsahuje adresu prvniho pixelu ve video RAM
 
        mov cx, 320*200/4   ; pocet prenesenych bajtu
        rep movsb           ; blokovy prenos po bajtech
        ret                 ; hotovo
 
move_image_part:
        mov si, image       ; nyni DS:SI obsahuje adresu prvniho bajtu v obrazku
        add si, ax          ; offset pixelu
        xor di, di          ; nyni ES:DI obsahuje adresu prvniho pixelu ve video RAM
 
        mov cx, 320*200/4   ; pocet zapisovanych bajtu (=pixelu)
.block_move:
        lodsb               ; nacist bajt z obrazku
        add si, 3           ; celkove posun o 4 pixely v obrazku 
        stosb               ; ulozit do obrazove pameti
        loop .block_move    ; presunout CX pixelu
        ret
 
; pridani binarnich dat s rastrovym obrazkem
image:
    incbin "image_320x200.bin"

13. Výsledky blokového přenosu

Nyní již bude celý rastrový obrázek přenesen (resp. přesněji řečeno zkopírován) naprosto bez problémů, což je patrné z následující dvojice screenshotů:

vga-bitblt-b-3

Obrázek 14: Obrazovka před provedením blokového přenosu obrázku.

vga-bitblt-b-4

Obrázek 15: Obrazovka po provedení blokového přenosu obrázku.

Poznámka: znovu si připomeňme, že z pohledu CPU bylo nutné přenést pouze 1/4 všech pixelů, což je významné urychlení, zejména na starších PC.

14. Logické operace prováděné při zápisu do obrazové paměti

Již v úvodní části dnešního článku jsme si řekli, že před zápisem osmice bitů do obrazové paměti se tyto bity rotují a taktéž se na ně aplikují logické operace, které jsou provedeny mezi zapisovanou hodnotou a hodnotou uloženou v latchi (obsah latche se nezmění). Následně pochopitelně závisí na tom, jak se výsledek interpretuje – pokud je totiž například povolen zápis jen do jediné bitové roviny, využije se jen 8 bitů výsledků a zbylých 24 bitů se bude ignorovat.

Logická operace je specifikována v nám již známém registru DATA_ROTATE ve dvou bitech:

+---+---+---+---+---+---+---+---+
| 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
+---+---+---+---+---+---+---+---+
|   |   |   |logická|  bitová   |
|   |   |   |operace|  rotace   |
+---+---+---+---+---+---+---+---+

Význam těchto dvou bitů je následující:

Bit 4 Bit 3 Prováděná operace
0 0 logická operace se neprovádí (přímý zápis)
0 1 logická operace AND
1 0 logická operace OR
1 1 logická operace XOR

15. Vyplnění části obrazovky s volitelnou aplikací logické operace

V poslední trojici demonstračních příkladů věnovaných grafické kartě VGA se v 16barevném režimu pokusíme o vykreslení barevných úseček (to již dobře známe) a následně vyplníme spodní polovinu obrazovky několika barevnými plochami (tj. výběrem různé kombinace bitových rovin):

        mov ax, 0xa000        ; video RAM v textovem rezimu
        mov es, ax
        mov ds, ax
        xor si, si            ; nyni DS:SI obsahuje adresu prvniho pixelu ve video RAM
        xor di, di            ; nyni ES:DI obsahuje adresu prvniho pixelu ve video RAM
 
        select_bitplane 0     ; vyber bitove roviny nebo bitovych rovin
        call fill_screen_area ; vypln casti obrazovky
 
        select_bitplane 1     ; vyber bitove roviny nebo bitovych rovin
        call fill_screen_area ; vypln casti obrazovky
 
        select_bitplane 7     ; vyber bitove roviny nebo bitovych rovin
        call fill_screen_area ; vypln casti obrazovky
 
        select_bitplane 8     ; vyber bitove roviny nebo bitovych rovin
        call fill_screen_area ; vypln casti obrazovky
 
        select_bitplane 15    ; vyber bitove roviny nebo bitovych rovin
        call fill_screen_area ; vypln casti obrazovky

Samotná výplň části obrazovky je řešena jednoduše (později dojde k nutné úpravě):

; vyplneni casti obrazovky
fill_screen_area:
        mov cx, 640*100/8   ; pocet zapisu
        mov al, 0xff        ; zapisovany vzorek
        rep stosb           ; provest vyplneni casti obrazovky (muze se vyuzit latch)
        ret                 ; hotovo

Přitom budeme sledovat, jak se bude výsledek lišit podle toho, jakou logickou operaci nastavíme. Ve výchozím stavu je provedení logických operací vypnuto, stejně jako je rotace bitů nastavena na nulu.

16. Vyplnění části obrazovky konstantní barvou při zákazu logických operací

Podívejme se nyní na to, jak vlastně bude vypadat obrazovka v 16barevném grafickém režimu před vyplněním obrazovky (tj. ve chvíli, kdy nakreslíme sadu barevných úseček) a po provedení vyplnění:

vga-bitblt-c-1

Obrázek 16: Původní obrazovka, prozatím před vyplněním.

vga-bitblt-c-2

Obrázek 17: Obrazovka po vyplnění její části „konstantní“ barvou.

Ze screenshotů je patrné, že jsme vlastně vyplnění neprovedli korektně, protože zápis (například) modré barvy pro nás znamenal, že se nastavily pouze bity v první bitové rovině a další roviny jsme při zápisu zcela ignorovali. Úsečky tedy nebyly zcela přemazány, což ovšem v některých případech nevadí – naopak se může jednat o žádoucí efekt.

Úplný kód demonstračního příkladu, který vykreslil obrázky číslo 16 a 17, vypadá následovně:

; Graficky rezim karty VGA s rozlisenim 640x480 pixelu.
; Zmena barvovych rovin, do kterych se zapisuje.
; Vykresleni barevnych usecek.
; Prekresleni s vyuzitim bezneho "MOV" rezimu.
;
; preklad pomoci:
;     nasm -f bin -o vga.com vga_write_mode_1.asm
;
; nebo pouze:
;     nasm -o vga.com vga_write_mode_1.asm
 
 
;-----------------------------------------------------------------------------
 
; I/O porty karty EGA/VGA
SEQUENCER_INDEX      equ 0x3c4
SEQUENCER_DATA       equ 0x3c5
 
; registry karty EGA/VGA
BITPLANE_SELECTOR    equ 0x02   ; controller
 
 
; 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
 
; vyber bitove roviny
%macro select_bitplane 1
        mov  al, %1         ; bitova rovina
        mov  dx, SEQUENCER_INDEX
        mov  ah, BITPLANE_SELECTOR
        xchg ah, al
        out  dx, ax         ; vyber registru sekvenceru
                            ; a zapis masky bitovych rovin
%endmacro
 
;-----------------------------------------------------------------------------
org  0x100        ; zacatek kodu pro programy typu COM (vzdy se zacina na 256)
 
start:
        gfx_mode 0x12         ; nastaveni rezimu 640x480 se sestnacti barvami
        call draw_color_lines
        wait_key              ; cekani na klavesu
 
        mov ax, 0xa000        ; video RAM v textovem rezimu
        mov es, ax
        mov ds, ax
        xor si, si            ; nyni DS:SI obsahuje adresu prvniho pixelu ve video RAM
        xor di, di            ; nyni ES:DI obsahuje adresu prvniho pixelu ve video RAM
 
        select_bitplane 0     ; vyber bitove roviny nebo bitovych rovin
        call fill_screen_area ; vypln casti obrazovky
 
        select_bitplane 1     ; vyber bitove roviny nebo bitovych rovin
        call fill_screen_area ; vypln casti obrazovky
 
        select_bitplane 7     ; vyber bitove roviny nebo bitovych rovin
        call fill_screen_area ; vypln casti obrazovky
 
        select_bitplane 8     ; vyber bitove roviny nebo bitovych rovin
        call fill_screen_area ; vypln casti obrazovky
 
        select_bitplane 15    ; vyber bitove roviny nebo bitovych rovin
        call fill_screen_area ; vypln casti obrazovky
 
        wait_key              ; cekani na klavesu
        exit                  ; navrat do DOSu
 
 
; vyplneni casti obrazovky
fill_screen_area:
        mov cx, 640*100/8   ; pocet zapisu
        mov al, 0xff        ; zapisovany vzorek
        rep stosb           ; provest vyplneni casti obrazovky (muze se vyuzit latch)
        ret                 ; hotovo
 
 
draw_color_lines:
        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, 480         ; hranice obrazovky?
        jne .opak           ; ne-opakujeme
        ret                 ; hotovo
 
 
; Vykresleni pixelu
; AX - x-ova souradnice
; BX - y-ova souradnice
; CL - barva
putpixel:
        push ax
        mov al, cl         ; vyber bitove roviny nebo bitovych rovin
        select_bitplane al
        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

17. Obnova obsahu latche před každým zápisem

V předchozím příkladu bylo vyplnění obrazovky realizováno tímto kódem, který do obrazové paměti pouze zapisovat bitový vzorek 0×ff:

; vyplneni casti obrazovky
fill_screen_area:
        mov cx, 640*100/8   ; pocet zapisu
        mov al, 0xff        ; zapisovany vzorek
        rep stosb           ; provest vyplneni casti obrazovky (muze se vyuzit latch)
        ret                 ; hotovo

To ovšem znamenalo, že latch stále obsahoval pouze původní hodnotu (z první a současně i poslední operace čtení). Pokud budeme chtít obsah latche (32 bitů) vždy obnovit před každým zápisem, je nutné funkci pro vyplnění obrazovky nepatrně upravit. Před každým zápisem jsou načteny obsahy bitových rovin (na korektním místě na obrazovce) do latche a následně je proveden zápis, s potenciálním využitím logických funkcí atd.:

; vyplneni casti obrazovky
fill_screen_area:
        mov cx, 640*100/8   ; pocet zapisu
.loop:
        lodsb               ; precteni hodnot do latche
        stosb               ; provest vyplneni casti obrazovky
        loop .loop
        ret                 ; hotovo

Výsledek bude (podle očekávání) odlišný:

vga-bitblt-d-1

Obrázek 18: Původní obrazovka, prozatím před vyplněním.

vga-bitblt-d-2

Obrázek 19: Obrazovka po vyplnění její části „konstantní“ barvou.

Následuje úplný zdrojový kód tohoto demonstračního příkladu, který vypadá následovně:

; Graficky rezim karty VGA s rozlisenim 640x480 pixelu.
; Zmena barvovych rovin, do kterych se zapisuje.
; Vykresleni barevnych usecek.
; Prekresleni s vyuzitim latche.
;
; preklad pomoci:
;     nasm -f bin -o vga.com vga_write_mode_2.asm
;
; nebo pouze:
;     nasm -o vga.com vga_write_mode_2.asm
 
 
;-----------------------------------------------------------------------------
 
; I/O porty karty EGA/VGA
SEQUENCER_INDEX      equ 0x3c4
SEQUENCER_DATA       equ 0x3c5
 
; registry karty EGA/VGA
BITPLANE_SELECTOR    equ 0x02   ; controller
 
 
; 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
 
; vyber bitove roviny
%macro select_bitplane 1
        mov  al, %1         ; bitova rovina
        mov  dx, SEQUENCER_INDEX
        mov  ah, BITPLANE_SELECTOR
        xchg ah, al
        out  dx, ax         ; vyber registru sekvenceru
                            ; a zapis masky bitovych rovin
%endmacro
 
;-----------------------------------------------------------------------------
org  0x100        ; zacatek kodu pro programy typu COM (vzdy se zacina na 256)
 
start:
        gfx_mode 0x12         ; nastaveni rezimu 640x480 se sestnacti barvami
        call draw_color_lines
        wait_key              ; cekani na klavesu
 
        mov ax, 0xa000        ; video RAM v textovem rezimu
        mov es, ax
        mov ds, ax
        xor si, si            ; nyni DS:SI obsahuje adresu prvniho pixelu ve video RAM
        xor di, di            ; nyni ES:DI obsahuje adresu prvniho pixelu ve video RAM
 
        select_bitplane 0     ; vyber bitove roviny nebo bitovych rovin
        call fill_screen_area ; vypln casti obrazovky
 
        select_bitplane 1     ; vyber bitove roviny nebo bitovych rovin
        call fill_screen_area ; vypln casti obrazovky
 
        select_bitplane 7     ; vyber bitove roviny nebo bitovych rovin
        call fill_screen_area ; vypln casti obrazovky
 
        select_bitplane 8     ; vyber bitove roviny nebo bitovych rovin
        call fill_screen_area ; vypln casti obrazovky
 
        select_bitplane 15    ; vyber bitove roviny nebo bitovych rovin
        call fill_screen_area ; vypln casti obrazovky
 
        wait_key              ; cekani na klavesu
        exit                  ; navrat do DOSu
 
 
; vyplneni casti obrazovky
fill_screen_area:
        mov cx, 640*100/8   ; pocet zapisu
.loop:
        lodsb               ; precteni hodnot do latche
        stosb               ; provest vyplneni casti obrazovky
        loop .loop
        ret                 ; hotovo
 
 
draw_color_lines:
        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, 480         ; hranice obrazovky?
        jne .opak           ; ne-opakujeme
        ret                 ; hotovo
 
 
; Vykresleni pixelu
; AX - x-ova souradnice
; BX - y-ova souradnice
; CL - barva
putpixel:
        push ax
        mov al, cl         ; vyber bitove roviny nebo bitovych rovin
        select_bitplane al
        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

18. Nastavení logické operace prováděné při zápisu do obrazové paměti

Nyní, když již víme, jakým způsobem lze obnovit obsah latche, se můžeme pokusit o nastavení vhodné logické operace prováděné při zápisu. Pro volbu logické operace použijeme toto makro:

; nastaveni logickeho rezimu pri zapisu
%macro write_logic_mode 1
        mov  dx, GRAPHICS_REGISTER
        mov  al, DATA_ROTATE
        out  dx, al         ; vyber VGA registru pro zapis
        inc  dx,
        mov  al, %1         ; zmena VGA registru
        out  dx, al
%endmacro

Připomeňme si, že v registru DATA_ROTATE se volí jak požadovaná logická operace, tak i rotace bitů při zápisu. Logická operace je určena čtvrtým a pátým bitem. Pokusme se nastavit operaci XOR (logické nonekvivalence):

        write_logic_mode 0b00110000  ; rezim XOR
 
        select_bitplane 0     ; vyber bitove roviny nebo bitovych rovin
        call fill_screen_area ; vypln casti obrazovky

Výsledek bude (opět zcela podle očekávání) odlišný:

vga-bitblt-c-3

Obrázek 20: Původní obrazovka, prozatím před vyplněním.

vga-bitblt-c-4

Obrázek 21: Obrazovka po vyplnění její části „konstantní“ barvou.

CS24 tip temata

Následuje úplný zdrojový kód dnešního posledního demonstračního příkladu:

; Graficky rezim karty VGA s rozlisenim 640x480 pixelu.
; Zmena barvovych rovin, do kterych se zapisuje.
; Vykresleni barevnych usecek.
; Prekresleni s vyuzitim logickeho rezimu.
;
; preklad pomoci:
;     nasm -f bin -o vga.com vga_write_mode_3.asm
;
; nebo pouze:
;     nasm -o vga.com vga_write_mode_3.asm
 
 
;-----------------------------------------------------------------------------
 
; I/O porty karty EGA/VGA
GRAPHICS_REGISTER    equ 0x3ce
SEQUENCER_INDEX      equ 0x3c4
SEQUENCER_DATA       equ 0x3c5
 
; registry karty EGA/VGA
BITPLANE_SELECTOR    equ 0x02   ; sequencer
DATA_ROTATE          equ 0x03   ; graphics register
GRAPHICS_MODE        equ 0x05   ; graphics register
 
 
; 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
 
; vyber bitove roviny
%macro select_bitplane 1
        mov  al, %1         ; bitova rovina
        mov  dx, SEQUENCER_INDEX
        mov  ah, BITPLANE_SELECTOR
        xchg ah, al
        out  dx, ax         ; vyber registru sekvenceru
                            ; a zapis masky bitovych rovin
%endmacro
 
; nastaveni logickeho rezimu pri zapisu
%macro write_logic_mode 1
        mov  dx, GRAPHICS_REGISTER
        mov  al, DATA_ROTATE
        out  dx, al         ; vyber VGA registru pro zapis
        inc  dx,
        mov  al, %1         ; zmena VGA registru
        out  dx, al
%endmacro
 
;-----------------------------------------------------------------------------
org  0x100        ; zacatek kodu pro programy typu COM (vzdy se zacina na 256)
 
start:
        gfx_mode 0x12         ; nastaveni rezimu 640x480 se sestnacti barvami
        call draw_color_lines
        wait_key              ; cekani na klavesu
 
        mov ax, 0xa000        ; video RAM v textovem rezimu
        mov es, ax
        mov ds, ax
        xor si, si            ; nyni DS:SI obsahuje adresu prvniho pixelu ve video RAM
        xor di, di            ; nyni ES:DI obsahuje adresu prvniho pixelu ve video RAM
 
        write_logic_mode 0b00110000  ; rezim XOR
 
        select_bitplane 0     ; vyber bitove roviny nebo bitovych rovin
        call fill_screen_area ; vypln casti obrazovky
 
        select_bitplane 1     ; vyber bitove roviny nebo bitovych rovin
        call fill_screen_area ; vypln casti obrazovky
 
        select_bitplane 7     ; vyber bitove roviny nebo bitovych rovin
        call fill_screen_area ; vypln casti obrazovky
 
        select_bitplane 8     ; vyber bitove roviny nebo bitovych rovin
        call fill_screen_area ; vypln casti obrazovky
 
        select_bitplane 15    ; vyber bitove roviny nebo bitovych rovin
        call fill_screen_area ; vypln casti obrazovky
 
        wait_key              ; cekani na klavesu
        exit                  ; navrat do DOSu
 
 
; vyplneni casti obrazovky
fill_screen_area:
        mov cx, 640*100/8   ; pocet zapisu
.loop:
        lodsb               ; precteni hodnoty do latche
        mov al, 0xf0        ; zapisovany vzorek
        stosb               ; provest vyplneni casti obrazovky
        loop .loop
        ret                 ; hotovo
 
 
draw_color_lines:
        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 useky
        call putpixel       ; vykreslení pixelu
        pop ax
 
        push ax
        mov cl, 12          ; barva
        add ax, 20          ; horizontalni posun useky
        call putpixel       ; vykreslení pixelu
        pop ax
 
        inc ax              ; pusun x+=1, y+=1
        cmp ax, 480         ; hranice obrazovky?
        jne .opak           ; ne-opakujeme
        ret                 ; hotovo
 
 
; Vykresleni pixelu
; AX - x-ova souradnice
; BX - y-ova souradnice
; CL - barva
putpixel:
        push ax
        mov al, cl         ; vyber bitove roviny nebo bitovych rovin
        select_bitplane al
        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

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

Demonstrační příklady napsané v assembleru, které jsou určené pro překlad s využitím assembleru NASM, byly uloženy 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
       
54 vga_text_mode_80×25.asm standardní textový režim 80×25 znaků na kartě VGA https://github.com/tisnik/8bit-fame/blob/master/pc-dos/vga_text_mode_80×25.asm
55 vga_text_mode_80×50.asm zobrazení 50 a taktéž 28 textových řádků na kartě VGA https://github.com/tisnik/8bit-fame/blob/master/pc-dos/vga_text_mode_80×50.asm
56 vga_text_mode_intensity1.asm změna chování atributového bitu pro blikání (nebezpečná varianta změny registrů) https://github.com/tisnik/8bit-fame/blob/master/pc-dos/vga_text_mode_intensity1.asm
57 vga_text_mode_intensity2.asm změna chování atributového bitu pro blikání (bezpečnější varianta změny registrů) https://github.com/tisnik/8bit-fame/blob/master/pc-dos/vga_text_mode_intensity2.asm
58 vga_text_mode_9th_column.asm modifikace způsobu zobrazení devátého sloupce ve znakových režimech (720 pixelů na řádku) https://github.com/tisnik/8bit-fame/blob/master/pc-dos/vga_text_mode_9th_column.asm
59 vga_text_mode_cursor_shape.asm změna tvaru textového kurzoru na grafické kartě VGA https://github.com/tisnik/8bit-fame/blob/master/pc-dos/vga_text_mode_cursor_shape.asm
60 vga_text_mode_custom_font.asm načtení vlastního fontu s jeho zobrazením https://github.com/tisnik/8bit-fame/blob/master/pc-dos/vga_text_mode_custom_font.asm
       
61 vga_gfx_mode_640×480.asm přepnutí do grafického režimu 640×480 pixelů se šestnácti barvami, vykreslení vzorků https://github.com/tisnik/8bit-fame/blob/master/pc-dos/vga_gfx_mode_640×480.asm
62 vga_gfx_mode_320×200.asm přepnutí do grafického režimu 320×200 pixelů s 256 barvami, vykreslení vzorků https://github.com/tisnik/8bit-fame/blob/master/pc-dos/vga_gfx_mode_320×200.asm
63 vga_gfx_mode_palette.asm změna všech barev v barvové paletě grafické karty VGA https://github.com/tisnik/8bit-fame/blob/master/pc-dos/vga_gfx_mode_palette.asm
64 vga_gfx_mode_dac1.asm využití DAC (neočekávané výsledky) https://github.com/tisnik/8bit-fame/blob/master/pc-dos/vga_gfx_mode_dac1.asm
65 vga_gfx_mode_dac2.asm využití DAC (očekávané výsledky) https://github.com/tisnik/8bit-fame/blob/master/pc-dos/vga_gfx_mode_dac2.asm
       
66 vga_640×480_putpixel.asm realizace algoritmu pro vykreslení pixelu v grafickém režimu 640×480 pixelů se šestnácti barvami https://github.com/tisnik/8bit-fame/blob/master/pc-dos/vga_640×480_putpixel.asm
67 vga_320×200_putpixel1.asm realizace algoritmu pro vykreslení pixelu v grafickém režimu 320×200 s 256 barvami (základní varianta) https://github.com/tisnik/8bit-fame/blob/master/pc-dos/vga_320×200_putpixel1.asm
68 vga_320×200_putpixel2.asm realizace algoritmu pro vykreslení pixelu v grafickém režimu 320×200 s 256 barvami (rychlejší varianta) https://github.com/tisnik/8bit-fame/blob/master/pc-dos/vga_320×200_putpixel2.asm
       
69 vga_gfx_mode_dac3.asm přímé využití DAC v grafickém režimu 13h https://github.com/tisnik/8bit-fame/blob/master/pc-dos/vga_gfx_mode_dac3.asm
       
70 vga_gfx_mode_unchained_step1.asm zobrazení barevných pruhů v režimu 13h https://github.com/tisnik/8bit-fame/blob/master/pc-dos/vga_gfx_mode_unchained_step1.asm
71 vga_gfx_mode_unchained_step2.asm vypnutí zřetězení bitových rovin a změna způsobu adresování pixelů https://github.com/tisnik/8bit-fame/blob/master/pc-dos/vga_gfx_mode_unchained_step2.asm
72 vga_gfx_mode_unchained_step3.asm vykreslení barevných pruhů do vybraných bitových rovin https://github.com/tisnik/8bit-fame/blob/master/pc-dos/vga_gfx_mode_unchained_step3.asm
       
73 vga_gfx_mode_320×400.asm nestandardní grafický režim s rozlišením 320×400 pixelů a 256 barvami https://github.com/tisnik/8bit-fame/blob/master/pc-dos/vga_gfx_mode_320×400.asm
74 vga_320×200_image.asm zobrazení rastrového obrázku ve standardním grafickém režimu 320×200 pixelů https://github.com/tisnik/8bit-fame/blob/master/pc-dos/vga_320×200_image.asm
75 vga_320×200_unchained_image1.asm zobrazení rastrového obrázku v režimu s nezřetězenými rovinami (nekorektní řešení) https://github.com/tisnik/8bit-fame/blob/master/pc-dos/vga_320×200_unchained_image1.asm
76 vga_320×200_unchained_image2.asm zobrazení rastrového obrázku v režimu s nezřetězenými rovinami (korektní řešení) https://github.com/tisnik/8bit-fame/blob/master/pc-dos/vga_320×200_unchained_image2.asm
77 vga_320×400_unchained_image.asm zobrazení rastrového obrázku v nestandardním režimu 320×400 pixelů https://github.com/tisnik/8bit-fame/blob/master/pc-dos/vga_320×400_unchained_image.asm
       
78 vga_vertical_scroll1.asm vertikální scrolling na kartě VGA v režimu s rozlišením 320×200 pixelů https://github.com/tisnik/8bit-fame/blob/master/pc-dos/vga_vertical_scroll1.asm
79 vga_vertical_scroll2.asm vertikální scrolling na kartě VGA v režimu s rozlišením 320×400 pixelů https://github.com/tisnik/8bit-fame/blob/master/pc-dos/vga_vertical_scroll2.asm
80 vga_split_screen1.asm režim split-screen a scrolling, nefunční varianta https://github.com/tisnik/8bit-fame/blob/master/pc-dos/vga_split_screen1.asm
81 vga_split_screen2.asm režim split-screen a scrolling, plně funkční varianta https://github.com/tisnik/8bit-fame/blob/master/pc-dos/vga_split_screen2.asm
82 vga_horizontal_scroll1.asm horizontální scrolling bez rozšíření počtu pixelů na virtuálním řádku https://github.com/tisnik/8bit-fame/blob/master/pc-dos/vga_horizontal_scroll1.asm
83 vga_horizontal_scroll2.asm horizontální scrolling s rozšířením počtu pixelů na virtuálním řádku https://github.com/tisnik/8bit-fame/blob/master/pc-dos/vga_horizontal_scroll2.asm
84 vga_horizontal_scroll3.asm jemný horizontální scrolling s rozšířením počtu pixelů na virtuálním řádku https://github.com/tisnik/8bit-fame/blob/master/pc-dos/vga_horizontal_scroll3.asm
       
85 vga_320×240_image.asm nastavení grafického režimu Mode-X, načtení a vykreslení obrázku, scrolling https://github.com/tisnik/8bit-fame/blob/master/pc-dos/vga_320×240_image.asm
       
86 io.asm knihovna maker pro I/O operace https://github.com/tisnik/8bit-fame/blob/master/pc-dos/io.asm
87 vga_lib.asm knihovna maker a podprogramů pro programování karty VGA https://github.com/tisnik/8bit-fame/blob/master/pc-dos/vga_lib.asm
88 vga_320×240_lib.asm nastavení grafického režimu Mode-X, tentokrát knihovními funkcemi https://github.com/tisnik/8bit-fame/blob/master/pc-dos/vga_320×240_lib.asm
       
89 vga_bitblt1.asm první (naivní) implementace operace BitBLT https://github.com/tisnik/8bit-fame/blob/master/pc-dos/vga_bitblt1.asm
90 vga_bitblt2.asm operace BitBLT s výběrem bitových rovin pro zápis https://github.com/tisnik/8bit-fame/blob/master/pc-dos/vga_bitblt2.asm
91 vga_bitblt3.asm operace BitBLT s výběrem bitových rovin pro čtení i zápis https://github.com/tisnik/8bit-fame/blob/master/pc-dos/vga_bitblt3.asm
92 vga_bitblt4.asm korektní BitBLT pro 16barevný režim, realizace makry https://github.com/tisnik/8bit-fame/blob/master/pc-dos/vga_bitblt4.asm
93 vga_bitblt5.asm korektní BitBLT pro 16barevný režim, realizace podprogramem https://github.com/tisnik/8bit-fame/blob/master/pc-dos/vga_bitblt5.asm
       
94 vga_bitblt_rotate.asm zápisový režim s rotací bajtu https://github.com/tisnik/8bit-fame/blob/master/pc-dos/vga_bitblt_rotate.asm
95 vga_bitblt_fast.asm rychlá korektní 32bitová operace typu BitBLT https://github.com/tisnik/8bit-fame/blob/master/pc-dos/vga_bitblt_fast.asm
96 vga_320×400_bitblt1.asm přenos obrázku v režimu 320×400 operací BitBLT (neúplná varianta) https://github.com/tisnik/8bit-fame/blob/master/pc-dos/vga_320×400_bitblt1.asm
97 vga_320×400_bitblt2.asm přenos obrázku v režimu 320×400 operací BitBLT (úplná varianta) https://github.com/tisnik/8bit-fame/blob/master/pc-dos/vga_320×400_bitblt2.asm
98 vga_write_modes1.asm volitelné zápisové režimy grafické karty VGA, zápis bez úpravy latche https://github.com/tisnik/8bit-fame/blob/master/pc-dos/vga_write_modes1.asm
99 vga_write_modes2.asm volitelné zápisové režimy grafické karty VGA, zápis s modifikací latche https://github.com/tisnik/8bit-fame/blob/master/pc-dos/vga_write_modes2.asm
100 vga_write_modes3.asm volitelné zápisové režimy grafické karty VGA, cílená modifikace latche vzorkem https://github.com/tisnik/8bit-fame/blob/master/pc-dos/vga_write_modes3.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
  82. Why were those colors chosen to be the default palette for 256-color VGA?
    https://retrocomputing.stac­kexchange.com/questions/27994/why-were-those-colors-chosen-to-be-the-default-palette-for-256-color-vga
  83. VGA Color Palettes
    https://www.fountainware.com/EX­PL/vga_color_palettes.htm
  84. Hardware Level VGA and SVGA Video Programming Information Page
    http://www.osdever.net/Fre­eVGA/vga/vga.htm
  85. Hardware Level VGA and SVGA Video Programming Information Page – sequencer
    http://www.osdever.net/Fre­eVGA/vga/seqreg.htm
  86. VGA Basics
    http://www.brackeen.com/vga/ba­sics.html
  87. Introduction to VGA Mode ‚X‘
    https://web.archive.org/web/20160414072210/htt­p://fly.srk.fer.hr/GDM/ar­ticles/vgamodex/vgamx1.html
  88. VGA Mode-X
    https://web.archive.org/web/20070123192523/htt­p://www.gamedev.net/referen­ce/articles/article356.asp
  89. Mode-X: 256-Color VGA Magic
    https://downloads.gamedev­.net/pdf/gpbb/gpbb47.pdf
  90. Instruction Format in 8086 Microprocessor
    https://www.includehelp.com/embedded-system/instruction-format-in-8086-microprocessor.aspx
  91. How to use „AND,“ „OR,“ and „XOR“ modes for VGA Drawing
    https://retrocomputing.stac­kexchange.com/questions/21936/how-to-use-and-or-and-xor-modes-for-vga-drawing
  92. VGA Hardware
    https://wiki.osdev.org/VGA_Hardware
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.

Autor článku

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