Hlavní navigace

Grafické operace přímo podporované čipy karty VGA

20. 8. 2024
Doba čtení: 57 minut

Sdílet

 Autor: Pinball Dreams
Dnes si popíšeme pokročilejší grafické operace podporované kartou VGA, které dokáží ušetřit práci CPU. Jedná se o horizontální i vertikální scrolling, podporu pro double i tripple buffering a taktéž o režim rozdělené obrazovky.

Obsah

1. Grafické operace přímo podporované čipy karty VGA

2. Vertikální scrolling

3. Čekání na dokončení vykreslení snímku

4. První demonstrační příklad: vertikální scrolling v režimu s rozlišením 320×200 pixelů

5. Scrolling v režimech s jiným rozlišením

6. Druhý demonstrační příklad: scrolling v režimu s rozlišením 320×400 pixelů

7. Double a tripple buffering

8. Režim split-screen

9. Konfigurace karty VGA pro použití split-screen

10. Třetí demonstrační příklad: (neúspěšný) pokus o nastavení split-screen

11. Korektní nastavení všech bitů hodnoty scan line compare

12. Čtvrtý demonstrační příklad: úspěšný pokus o nastavení split-screen

13. Horizontální scrolling

14. Pátý demonstrační příklad: horizontální scrolling o čtyři pixely beze změny délky řádků

15. Změna počtu pixelů na obrazových řádcích bez změny rozlišení

16. Šestý demonstrační příklad: horizontální scrolling při šířce řádků nastavených na 640 pixelů

17. Jemný horizontální scrolling

18. Sedmý demonstrační příklad: jemný horizontální scrolling

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

20. Odkazy na Internetu

1. Grafické operace přímo podporované čipy karty VGA

Grafická karta VGA byla používána společně s mikroprocesory Intel 80286 a Intel 80386, což jsou z dnešního pohledu dosti pomalé čipy. Navíc byla VGA v naprosté většině případů propojena přes (opět relativně pomalou) sběrnici ISA. Bylo tedy velmi žádoucí, aby co největší množství grafických operací bylo podporováno přímo kartou VGA, což umožnilo do značné míry omezit datový tok mezi mikroprocesorem a grafickou kartou. Karta VGA skutečně byla připravena pro provádění některých z těchto operací, zejména pak:

  1. Zápis většího množství pixelů se stejnou barvou (díky bitovým rovinám)
  2. Blokové přenosy dat mezi částmi grafické paměti bez nutnosti jejich čtení/zápisu do CPU
  3. Jemný vertikální scrolling obrazovky po jednotlivých obrazových řádcích
  4. Hrubý i jemný horizontální scrolling obrazovky po bajtech nebo po pixelech
  5. Takzvaný režim split screen, kdy jsou dvě části obrazovky uloženy na odlišných adresách a jedna část podporuje scrolling
  6. Podpora pro double i tripple buffering umožňující vykreslování grafické scény na pozadí
  7. Takzvaný windowing, v němž je obrazovka součástí větší plochy (souvisí se scrollingem)

Některé z těchto operací již známe (zápis většího množství pixelů), další si popíšeme v dnešním článku.

Obrázek 1: Některé dále popsané možnosti karty VGA jsou použity ve hře Pinball Dreams.

2. Vertikální scrolling

Začneme implementačně velmi jednoduchou grafickou operací – vertikálním scrollingem. Ten umožňuje plynulý posun obrazu nahoru a dolů, přičemž se na uvolněném místě zobrazí obsah dalších obrazových řádků. V nezřetězených grafických režimech s horizontálním rozlišením 320 pixelů je k dispozici celkem:

256 × 1024 / 320 = 819

obrazových řádků, ovšem zobrazeno jich je většinou jen 200, 240, 400 nebo 480 (podle zvoleného režimu). Úpravou registrů CRTC můžeme docílit toho, že se na prvním řádku monitoru zobrazí řádek od určené adresy (v segmentu 0×a000). Pokud budeme tuto adresu zvyšovat nebo snižovat o hodnotu 80 (počet pixelů na řádku v nezřetězeném grafickém režimu), dosáhneme plynulého vertikálního scrollingu.

Nejprve si připravíme potřebné konstanty a makra. Adresy I/O portů pro registry CRTC již známe:

CRTC_INDEX           equ 0x3d4
CRTC_DATA            equ 0x3d5

Pracovat budeme s registry s poměrně přesným názvem START_ADDRESS_HIGH a START_ADDRESS_LOW, které mají tyto indexy:

START_ADDRESS_HIGH   equ 0x0c   ; CRTC
START_ADDRESS_LOW    equ 0x0d   ; CRTC

Makro pro nastavení libovolného registru CRTC již taktéž známe, takže jen pro úplnost:

; 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

Samotný vertikální posun je snadný. V případě, že bude adresa ve video paměti, od níž se má provádět vykreslování, uložena v registru BX, můžeme VGA nastavit tímto způsobem:

set_crtc_register START_ADDRESS_HIGH, bh
set_crtc_register START_ADDRESS_LOW, bl

Samotný postupný vertikální scrolling o 200 obrazových řádků lze realizovat touto sekvencí instrukcí (které nepřenesou do video paměti ani jediný bajt):

        mov cx, 200         ; pocet radku, o ktere budeme scrollovat
        xor bx, bx          ; adresa zacatku vykreslovani
 
opak:
        add bx, 80          ; prechod na dalsi adresu, od ktere se bude vykreslovat
        call wait_sync      ; cekani na sync.
                            ; zmena adresy
        set_crtc_register START_ADDRESS_HIGH, bh
        set_crtc_register START_ADDRESS_LOW, bl
        loop opak

Obrázek 2: Další snímek ze hry Pinball Dreams.

3. Čekání na dokončení vykreslení snímku

Výše uvedený příklad má dva problémy: může dojít k „roztržení“ obrazu, pokud se mezi změnou horní a dolní poloviny adresy začne vykreslovat nový snímek. A problémy může způsobit taktéž jiné přerušení (třeba po stisku klávesy). Musíme tedy zajistit, aby se změna adresy provedla ve vhodný okamžik – a to konkrétně v čase mezi vykreslením snímků (a ideálně i zakázat přerušení, což je však koncept, který prozatím neznáme).

Realizace čekání na vertikální přerušení je sice – samozřejmě pokud nám nevadí „pálení strojového času“ – vlastně až primitivně jednoduché. Postačuje nám totiž kontinuálně sledovat čtvrtý bit portu 0×3da. Pokud je tento bit nastaven, probíhá vertikální přerušení (a změnu je tedy možné provést); jinak neprobíhá. Jenže ono to v praxi není až tak jednoduché, protože i když je tento bit nastaven, tak vlastně nevíme, zda přerušení v dalším cyklu neskončí (nevíme, ve kterém okamžiku přerušení se nacházíme). Musíme tedy provádět dvě operace: čekání na dokončení aktuálního přerušení (pokud probíhá) a čekání na nové přerušení, tedy na jeho začátek. Celá realizace čekání na začátek vertikálního přerušení vypadá takto:

wait_sync:
        mov dx, INPUT_STATUS ; adresa stavoveho registru graficke karty CGA
wait_sync_end:
        in al, dx           ; precteni hodnoty stavoveho registru
        test al, V_RETRACE  ; odmaskovat priznak vertikalniho synchronizacniho pulsu
        jnz wait_sync_end   ; probiha - cekat na konec
wait_sync_start:
        in al, dx           ; precteni hodnoty stavoveho registru
        test al, V_RETRACE  ; odmaskovat priznak vertikalniho synchronizacniho pulsu
        jz wait_sync_start  ; neprobiha - cekat na zacatek
        ret                 ; ok - synchronizacni kurz probiha, lze zapisovat do pameti
Poznámka: to má další důsledek – vertikální scrolling bude stejně rychlý nezávisle na rychlosti počítače – dosáhne 70 řádků za sekundu.

Výsledkem bude plynulý vertikální scrolling:

Obrázek 3: Obsah obrazovky přes začátkem scrollingu.

Obrázek 4: Průběh vertikálního scrollingu.

Obrázek 5: Průběh vertikálního scrollingu.

4. První demonstrační příklad: vertikální scrolling v režimu s rozlišením 320×200 pixelů

V dnešním prvním demonstračním příkladu je ukázána realizace vertikálního scrollingu v grafickém režimu s rozlišením 320×200 pixelů. Musí se pochopitelně jednat o režim s nesřetězenými bitovými rovinami, protože ve standardním režimu 13h není „kam scrollovat“ (maximálně o několik obrazových řádků na adresách 64000..65535, což není mnoho, konkrétně jen čtyři obrazové řádky). Aby nebyl scrolling příliš rychlý a aby se obraz netrhal, čeká se vždy na vykreslení celého snímku, což zajišťuje frekvenci 70 snímků (posunů) za sekundu:

; Graficky rezim karty VGA s rozlisenim 320x200 pixelu.
; Vypnuti zretezeni bitovych rovin.
; Vykresleni rastroveho obrazku postupne do vsech bitovych rovin.
; Vertikalni scrolling po stisku klavesy.
;
; preklad pomoci:
;     nasm -f bin -o vga.com vga_vertical_scroll_1.asm
;
; nebo pouze:
;     nasm -o vga.com vga_vertical_scroll_1.asm
 
 
;-----------------------------------------------------------------------------
 
; registry karty VGA
SEQUENCER_INDEX      equ 0x3c4
SEQUENCER_DATA       equ 0x3c5
CRTC_INDEX           equ 0x3d4
CRTC_DATA            equ 0x3d5
INPUT_STATUS         equ 0x3da
BITPLANE_SELECTOR    equ 0x02
MEMORY_MODE_REGISTER equ 0x04   ; sekvencer
UNDERLINE_LOCATION   equ 0x14   ; CRTC
MODE_CONTROL         equ 0x17   ; CRTC
START_ADDRESS_HIGH   equ 0x0c   ; CRTC
START_ADDRESS_LOW    equ 0x0d   ; CRTC
 
; bitove masky
V_RETRACE            equ 0x08
 
; 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
 
        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
 
        mov cx, 200         ; pocet radku, o ktere budeme scrollovat
        xor bx, bx          ; adresa zacatku vykreslovani
 
opak:
        add bx, 80          ; prechod na dalsi adresu, od ktere se bude vykreslovat
        call wait_sync      ; cekani na sync.
                            ; zmena adresy
        set_crtc_register START_ADDRESS_HIGH, bh
        set_crtc_register START_ADDRESS_LOW, bl
        loop opak
 
        wait_key            ; cekani na klavesu
        exit                ; navrat do DOSu
 
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)
bitblt:
        lodsb               ; nacist bajt z obrazku
        add si, 3           ; celkove posun o 4 pixely v obrazku 
        stosb               ; ulozit do obrazove pameti
        loop bitblt         ; presunout CX pixelu
        ret
 
wait_sync:
        mov dx, INPUT_STATUS ; adresa stavoveho registru graficke karty CGA
wait_sync_end:
        in al, dx           ; precteni hodnoty stavoveho registru
        test al, V_RETRACE  ; odmaskovat priznak vertikalniho synchronizacniho pulsu
        jnz wait_sync_end   ; probiha - cekat na konec
wait_sync_start:
        in al, dx           ; precteni hodnoty stavoveho registru
        test al, V_RETRACE  ; odmaskovat priznak vertikalniho synchronizacniho pulsu
        jz wait_sync_start  ; neprobiha - cekat na zacatek
        ret                 ; ok - synchronizacni kurz probiha, lze zapisovat do pameti
 
; pridani binarnich dat s rastrovym obrazkem
image:
    incbin "image_320x200.bin"

5. Scrolling v režimech s jiným rozlišením

Scrolling lze pochopitelně realizovat v prakticky jakémkoli grafickém režimu, jak šestnáctibarevném, tak i 256barevném. Určitou výjimkou je standardní režim 13h, kde již kvůli zřetězení bitových rovin nezbývá kapacita video paměti. Velmi často se ovšem se scrollingem setkáme u nestandardních grafických režimů s 256 barvami, které z režimu 13h vychází. Zajímavé bude zjistit, kolik plochy (měřené v obrazových řádcíc) nebo celých obrazovkách) vlastně máme v různých režimech k dispozici. V další tabulce jsou vypsány ty nejpoužívanější nestandardní grafické režimy:

Rozlišení Obrazovka Počet řádků celkem Výška (obrazovek) Poznámka
256×256 65536 1024 4 známé jako Mode-Q: 256×256×256 neboli q©ube
320×200 64000 819 4 známé jako Mode-Y, vychází ze standardního grafického režimu 13h
320×240 76800 819 3 známé jako Mode-X
320×400 128000 819 2 dvojnásobný počet řádků oproti Mode-Y
320×480 153600 819 1 dvojnásobný počet řádků oproti Mode-X
360×240 86400 728 3 využití možnosti VGA zobrazit 720 (360) pixelů na řádku (vychází z textového režimu)
360×480 172800 728 1 nejlepší rozlišení, které je kompatibilní se všemi monitory
400×300 120000 655 2 nejlepší rozlišení 4:3, které je většinou kompatibilní s multisync monitory

Můžeme si například vykoušet scrolling v režimu 320×400 s 256 barvami. Nejdříve režim nastavíme, což je snadné:

gfx_mode 0x13       ; nastaveni rezimu 320x200 s 256 barvami
 
; 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

Následně je již možné realizovat „nasunutí“ obrázku na plochu obrazovky:

        mov cx, 400         ; pocet radku, o ktere budeme scrollovat
        xor bx, bx          ; adresa zacatku vykreslovani
 
opak:
        add bx, 80          ; prechod na dalsi adresu, od ktere se bude vykreslovat
        call wait_sync      ; cekani na sync.
                            ; zmena adresy
        set_crtc_register START_ADDRESS_HIGH, bh
        set_crtc_register START_ADDRESS_LOW, bl
        loop opak

Obrázek 6: Obsah obrazovky 320×400 přes začátkem scrollingu.

Obrázek 7: Průběh vertikálního scrollingu.

Obrázek 8: Průběh vertikálního scrollingu.

6. Druhý demonstrační příklad: scrolling v režimu s rozlišením 320×400 pixelů

V dnešním druhém příkladu, který je vlastně do značné míry podobný příkladu prvnímu, je taktéž realizován vertikální scrolling, tentokrát však v grafickém režimu s rozlišením 320×400 pixelů. Úplný zdrojový kód tohoto příkladu vypadá následovně:

; Graficky rezim karty VGA s rozlisenim 320x400 pixelu.
; Vypnuti zretezeni bitovych rovin.
; Vykresleni rastroveho obrazku postupne do vsech bitovych rovin.
; Vertikalni scrolling po stisku klavesy.
;
; preklad pomoci:
;     nasm -f bin -o vga.com vga_vertical_scroll_2.asm
;
; nebo pouze:
;     nasm -o vga.com vga_vertical_scroll_2.asm
 
 
;-----------------------------------------------------------------------------
 
; registry karty VGA
SEQUENCER_INDEX      equ 0x3c4
SEQUENCER_DATA       equ 0x3c5
CRTC_INDEX           equ 0x3d4
CRTC_DATA            equ 0x3d5
INPUT_STATUS         equ 0x3da
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
START_ADDRESS_HIGH   equ 0x0c   ; CRTC
START_ADDRESS_LOW    equ 0x0d   ; CRTC
 
; bitove masky
V_RETRACE            equ 0x08
 
; 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
 
        mov cx, 400         ; pocet radku, o ktere budeme scrollovat
        xor bx, bx          ; adresa zacatku vykreslovani
 
opak:
        add bx, 80          ; prechod na dalsi adresu, od ktere se bude vykreslovat
        call wait_sync      ; cekani na sync.
                            ; zmena adresy
        set_crtc_register START_ADDRESS_HIGH, bh
        set_crtc_register START_ADDRESS_LOW, bl
        loop opak
 
        wait_key            ; cekani na klavesu
        exit                ; navrat do DOSu
 
move_image_part:
        mov si, image       ; nyni DS:SI obsahuje adresu prvniho bajtu v obrazku
        add si, ax          ; offset pixelu
        mov di, 320*100     ; nyni ES:DI obsahuje adresu prvniho pixelu ve video RAM
                            ; kam budeme chtit provest vykreslovani
 
        mov cx, 320*200/4   ; pocet zapisovanych bajtu (=pixelu)
bitblt:
        lodsb               ; nacist bajt z obrazku
        add si, 3           ; celkove posun o 4 pixely v obrazku 
        stosb               ; ulozit do obrazove pameti
        loop bitblt         ; presunout CX pixelu
        ret
 
wait_sync:
        mov dx, INPUT_STATUS ; adresa stavoveho registru graficke karty CGA
wait_sync_end:
        in al, dx           ; precteni hodnoty stavoveho registru
        test al, V_RETRACE  ; odmaskovat priznak vertikalniho synchronizacniho pulsu
        jnz wait_sync_end   ; probiha - cekat na konec
wait_sync_start:
        in al, dx           ; precteni hodnoty stavoveho registru
        test al, V_RETRACE  ; odmaskovat priznak vertikalniho synchronizacniho pulsu
        jz wait_sync_start  ; neprobiha - cekat na zacatek
        ret                 ; ok - synchronizacni kurz probiha, lze zapisovat do pameti
 
; pridani binarnich dat s rastrovym obrazkem
image:
    incbin "image_320x200.bin"

7. Double a tripple buffering

V nestandardních 256barevných režimech lze snadno realizovat další dvě důležité grafické operace: double buffering a tripple buffering. Jedná se vlastně o vertikální scrolling o celou výšku obrazovky (200, 240 atd. řádků). Kolik takových obrazovek je k dispozici již vlastně víme z tabulky uvedené v páté kapitole:

Rozlišení Obrazovka Výška (obrazovek) Poznámka
256×256 65536 4 známé jako Mode-Q: 256×256×256 neboli q©ube
320×200 64000 4 známé jako Mode-Y, vychází ze standardního grafického režimu 13h
320×240 76800 3 známé jako Mode-X
320×400 128000 2 dvojnásobný počet řádků oproti Mode-Y
320×480 153600 1 dvojnásobný počet řádků oproti Mode-X
360×240 86400 3 využití možnosti VGA zobrazit 720 (360) pixelů na řádku (vychází z textového režimu)
360×480 172800 1 nejlepší rozlišení, které je kompatibilní se všemi monitory
400×300 120000 2 nejlepší rozlišení 4:3, které je většinou kompatibilní s multisync monitory

K čemu tyto operace slouží? Double buffering umožňuje, aby se scéna překreslila na pozadí (do zadního bufferu), přičemž zobrazená bude v tomto čase předchozí verze scény (přední buffer). A teprve po překreslení celého snímku se provede přepnutí: zadní buffer se stane bufferem předním a naopak. Přepínání je vhodné provádět mezi vykreslením snímků, tedy v době vertikálního přerušení.

Ovšem čekání na vertikální přerušení znamená, že se mikroprocesor v tomto čase nebude věnovat užitečnější činnosti, tj. výpočtu další scény. A právě v této chvíli lze využít tripple buffering, kdy jeden buffer je zobrazen, další je již vykreslen a čeká se na vhodný čas pro přepnutí bufferů a mezitím lze vykreslování provádět do třetího bufferu. Tripple buffering je podporován například režimem X, ovšem ne již režimem s rozlišením 320×400 řádků (zde nemáme k dispozici dostatek video paměti).

8. Režim split-screen

Se scrollingem souvisí i další zajímavá vlastnost grafické karty VGA. Tato karta totiž podporuje režim split-screen. O co se jedná? Obrazovka je logicky rozdělena na dvě části, přičemž první část je vykreslována od adresy určené již známými CRTC registry START_ADDRESS_HIGH aSTART_ADDRESS_LOW (což již známe), zatímco část druhá má fixně nastavenou počáteční adresu na nulu (v segmentu 0×a000). Jedna část obrazovky tedy může volně scrollovat, zatímco druhá nikoli, což například umožňuje zobrazit pruh se skóre, instrukcemi atd. Nebo lze realizovat hry s rozdělenou obrazovkou, kde pro prvního hráče získáme možnost scrollingu „zadarmo“ (bez nutnosti přenosu dat), zatímco pro část obrazovky vyhrazené pro druhého hráče je již nutné scrolling realizovat programově (přenosem z RAM nebo z neviditelné části video RAM).

Poznámka: teoreticky lze split screen použít v jakémkoli grafickém režimu, ale i v režimu textovém, protože z pohledu CRTC registrů se tyto režimy vlastně chovají podobně.

Obrázek 9: Rozdělení obsahu obrazovky v režimu split-screen.

9. Konfigurace karty VGA pro použití split-screen

Pro nastavení split screenu nám vlastně postačuje maličkost – nastavit hodnotu nazývanou scan line compare. Jedná se o hodnotu, se kterou se porovnává aktuální hodnota počitadla řádků. Pokud se skutečně dosáhne nastaveného limitu, provede karta VGA „reset“ adresy dalšího pixelu na nulu – tak snadné to interně je.

Praxe je pochopitelně složitější, protože hodnota scan line compare je desetibitová (rozsah 0..1023) a registry CRTC jsou osmibitové. Teoreticky by bylo možné tuto hodnotu rozdělit do dvou po sobě jdoucích registrů, ale IBM se s programátory nemazlí – oněch deset bitů je rozděleno do tří registrů (což by ještě nevadilo), jenže navíc obsahují tyto tři registry i další bity, takže modifikace znamená bitové operace atd.:

Bit(y) Registr Index Bit v registru
0–7 Line Compare 0×18 0–7
8 Overflow 0×07 4
9 Maximum scan line 0×09 6

10. Třetí demonstrační příklad: (neúspěšný) pokus o nastavení split-screen

Pokusme se nyní modifikovat předchozí příklad pro vertikální scrolling tak, že obrazovku rozdělíme na dvě části změnou registru LINE_COMPARE obsahujícího spodních osm bitů hodnoty scan line compare. Rozdělení obrazovky na přesné poloviny znamená dosazení hodnoty 200, protože již víme, že v režimu 320×200 jsou řádky zdvojeny (každý je vykreslen dvakrát):

set_crtc_register LINE_COMPARE, 200               ; rezim split-screen na radku 200

Bude to fungovat? Prozatím nikoli, o čemž se snadno přesvědčíme:

Obrázek 10: Scrolluje celá obrazovka – režim split-screen nefunguje podle očekávání.

Pro úplnost si ukažme, jak vypadá celý zdrojový kód tohoto příkladu:

; Graficky rezim karty VGA s rozlisenim 320x400 pixelu.
; Vypnuti zretezeni bitovych rovin.
; Nastaveni split screen.
; Vykresleni rastroveho obrazku postupne do vsech bitovych rovin.
; Vertikalni scrolling po stisku klavesy.
;
; preklad pomoci:
;     nasm -f bin -o vga.com vga_split_screen_1.asm
;
; nebo pouze:
;     nasm -o vga.com vga_split_screen_1.asm
 
 
;-----------------------------------------------------------------------------
 
; registry karty VGA
SEQUENCER_INDEX      equ 0x3c4
SEQUENCER_DATA       equ 0x3c5
CRTC_INDEX           equ 0x3d4
CRTC_DATA            equ 0x3d5
INPUT_STATUS         equ 0x3da
BITPLANE_SELECTOR    equ 0x02
MEMORY_MODE_REGISTER equ 0x04   ; sekvencer
OVERFLOW             equ 0x07   ; CRTC
MAXIMUM_SCAN_LINE    equ 0x09   ; CRTC
UNDERLINE_LOCATION   equ 0x14   ; CRTC
MODE_CONTROL         equ 0x17   ; CRTC
LINE_COMPARE         equ 0x18   ; CRTC
START_ADDRESS_HIGH   equ 0x0c   ; CRTC
START_ADDRESS_LOW    equ 0x0d   ; CRTC
 
; bitove masky
V_RETRACE            equ 0x08
 
; 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 LINE_COMPARE, 200               ; rezim split-screen na radku 200
 
        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
 
        mov cx, 100         ; pocet radku, o ktere budeme scrollovat
        xor bx, bx          ; adresa zacatku vykreslovani
 
opak:
        add bx, 80          ; prechod na dalsi adresu, od ktere se bude vykreslovat
        call wait_sync      ; cekani na sync.
                            ; zmena adresy
        set_crtc_register START_ADDRESS_HIGH, bh
        set_crtc_register START_ADDRESS_LOW, bl
        loop opak
 
        wait_key            ; cekani na klavesu
        exit                ; navrat do DOSu
 
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)
bitblt:
        lodsb               ; nacist bajt z obrazku
        add si, 3           ; celkove posun o 4 pixely v obrazku 
        stosb               ; ulozit do obrazove pameti
        loop bitblt         ; presunout CX pixelu
        ret
 
wait_sync:
        mov dx, INPUT_STATUS ; adresa stavoveho registru graficke karty CGA
wait_sync_end:
        in al, dx           ; precteni hodnoty stavoveho registru
        test al, V_RETRACE  ; odmaskovat priznak vertikalniho synchronizacniho pulsu
        jnz wait_sync_end   ; probiha - cekat na konec
wait_sync_start:
        in al, dx           ; precteni hodnoty stavoveho registru
        test al, V_RETRACE  ; odmaskovat priznak vertikalniho synchronizacniho pulsu
        jz wait_sync_start  ; neprobiha - cekat na zacatek
        ret                 ; ok - synchronizacni kurz probiha, lze zapisovat do pameti
 
; pridani binarnich dat s rastrovym obrazkem
image:
    incbin "image_320x200.bin"

11. Korektní nastavení všech bitů hodnoty scan line compare

Aby bylo možné korektně nastavit režim rozdělené obrazovky, je nutné modifikovat všech deset bitů hodnoty max line compare, tedy včetně osmého bitu (registr Overflow) a bitu devátého (registr Maximum scan line). Budeme chtít obrazovku rozdělit v režimu 320×200 pixelů v polovině, tj. na řádku 100. Ovšem již víme, že v tomto režimu se každý řádek vykresluje dvakrát, takže budeme muset nastavit hodnotu 200. Ukažme si jednotlivé kroky:

V prvním kroku nastavíme spodních osm bitů, což je nejsnadnější, protože použijeme makro:

set_crtc_register LINE_COMPARE, 200

Dále vynulujeme devátý bit, jenž je umístěný v CRTC registru Overflow. Zde musíme použít bitovou masku aplikovanou na původní obsah registru (ostatní bity totiž nesmíme modifikovat):

mov dx, CRTC_INDEX
mov al, OVERFLOW
out dx, al
inc dx
in  al, dx
and al, 0xef
out dx, al

A nakonec vynulujeme bit desátý, který je umístěn v registru Maximum scan line. Opět je nutné použít bitovou masku:

mov dx, CRTC_INDEX
mov al, MAXIMUM_SCAN_LINE
out dx, al
inc dx
in  al, dx
and al, 0xbf
out dx, al

Výsledek:

Obrázek 11: Vertikální scrolling v režimu split screen.

Obrázek 12: Vertikální scrolling v režimu split screen.

Obrázek 13: Vertikální scrolling v režimu split screen.

12. Čtvrtý demonstrační příklad: úspěšný pokus o nastavení split-screen

Upravené a již skutečně funkční nastavení režimu rozdělené obrazovky (split screen) je ukázáno v dnešním čtvrtém demonstračním příkladu, jehož úplný zdrojový kód vypadá následovně:

; Graficky rezim karty VGA s rozlisenim 320x200 pixelu.
; Vypnuti zretezeni bitovych rovin.
; Nastaveni split screen.
; Vykresleni rastroveho obrazku postupne do vsech bitovych rovin.
; Vertikalni scrolling po stisku klavesy.
;
; preklad pomoci:
;     nasm -f bin -o vga.com vga_split_screen_2.asm
;
; nebo pouze:
;     nasm -o vga.com vga_split_screen_2.asm
 
 
;-----------------------------------------------------------------------------
 
; registry karty VGA
SEQUENCER_INDEX      equ 0x3c4
SEQUENCER_DATA       equ 0x3c5
CRTC_INDEX           equ 0x3d4
CRTC_DATA            equ 0x3d5
INPUT_STATUS         equ 0x3da
BITPLANE_SELECTOR    equ 0x02
MEMORY_MODE_REGISTER equ 0x04   ; sekvencer
OVERFLOW             equ 0x07   ; CRTC
MAXIMUM_SCAN_LINE    equ 0x09   ; CRTC
UNDERLINE_LOCATION   equ 0x14   ; CRTC
MODE_CONTROL         equ 0x17   ; CRTC
LINE_COMPARE         equ 0x18   ; CRTC
START_ADDRESS_HIGH   equ 0x0c   ; CRTC
START_ADDRESS_LOW    equ 0x0d   ; CRTC
 
; bitove masky
V_RETRACE            equ 0x08
 
; 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 LINE_COMPARE, 200
 
        mov dx, CRTC_INDEX
        mov al, MAXIMUM_SCAN_LINE
        out dx, al
        inc dx
        in al, dx
        and al, 0xbf
        out dx, al
 
        mov dx, CRTC_INDEX
        mov al, OVERFLOW
        out dx, al
        inc dx
        in al, dx
        and al, 0xef
        out dx, al
 
        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
 
        mov cx, 100         ; pocet radku, o ktere budeme scrollovat
        xor bx, bx          ; adresa zacatku vykreslovani
 
opak:
        add bx, 80          ; prechod na dalsi adresu, od ktere se bude vykreslovat
        call wait_sync      ; cekani na sync.
                            ; zmena adresy
        set_crtc_register START_ADDRESS_HIGH, bh
        set_crtc_register START_ADDRESS_LOW, bl
        loop opak
 
        wait_key            ; cekani na klavesu
        exit                ; navrat do DOSu
 
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)
bitblt:
        lodsb               ; nacist bajt z obrazku
        add si, 3           ; celkove posun o 4 pixely v obrazku 
        stosb               ; ulozit do obrazove pameti
        loop bitblt         ; presunout CX pixelu
        ret
 
wait_sync:
        mov dx, INPUT_STATUS ; adresa stavoveho registru graficke karty CGA
wait_sync_end:
        in al, dx           ; precteni hodnoty stavoveho registru
        test al, V_RETRACE  ; odmaskovat priznak vertikalniho synchronizacniho pulsu
        jnz wait_sync_end   ; probiha - cekat na konec
wait_sync_start:
        in al, dx           ; precteni hodnoty stavoveho registru
        test al, V_RETRACE  ; odmaskovat priznak vertikalniho synchronizacniho pulsu
        jz wait_sync_start  ; neprobiha - cekat na zacatek
        ret                 ; ok - synchronizacni kurz probiha, lze zapisovat do pameti
 
; pridani binarnich dat s rastrovym obrazkem
image:
    incbin "image_320x200.bin"

13. Horizontální scrolling

Nyní si popišme způsob realizace horizontálního scrollingu. Jedná se o poněkud složitější techniku, než scrolling vertikální, a to ze dvou důvodů:

  1. Obrazové řádky musí být delší (minimálně o jeden pixel) než šířka obrazovky, aby se při horizontálním scrollingu na volné místo nepřesunovaly pixely z jiných řádků.
  2. Musíme umět zajistit posun ideálně o jednotlivé pixely, popř. alespoň o dva pixely. Ovšem v nezřetězených režimech je hrubý posun vždy o čtyři pixely.

Nicméně začněme prozatím tím nejjednodušším možným příkladem, v němž nebudou obrazové řádky delší než šířka obrazovky a taktéž nebudeme provádět „jemný“ scrolling, ale scrolling o celé bajty (což v 256 barevných režimech znamená posun o čtyři pixely – nesmíme zapomenout na to, že roviny nejsou zřetězeny!).

Následující sekvence strojových instrukcí nám umožní realizovat horizontální scrolling o celou šířku obrazovky (postupně), ovšem ve skocích po čtyřech pixelech. Obrazovka se tak odskroluje celkem 80× (oproti vertikálnímu scrollingu počáteční adresu pro zobrazování měníme po jedné a nikoli po 80):

        mov cx, 80          ; pocet bajtu(!), o ktere budeme scrollovat
        xor bx, bx          ; adresa zacatku vykreslovani
 
opak:
        inc bx              ; posun o jediny pixel
        call wait_sync      ; cekani na sync.
                            ; zmena adresy
        set_crtc_register START_ADDRESS_HIGH, bh
        set_crtc_register START_ADDRESS_LOW, bl
        loop opak
 
        wait_key            ; cekani na klavesu
        exit                ; navrat do DOSu

Výsledky mohou vypadat následovně – povšimněte si, jak se při scrollingu na řádky nasouvá obsah následujících řádků (což ovšem v praxi nebudeme chtít):

Obrázek 14: Horizontální scrolling beze změny délky obrazových řádků.

14. Pátý demonstrační příklad: horizontální scrolling o čtyři pixely beze změny délky řádků

Úplný zdrojový kód příkladu pro „hrubý“ horizontální scrolling může vypadat následovně:

; Graficky rezim karty VGA s rozlisenim 320x400 pixelu.
; Vypnuti zretezeni bitovych rovin.
; Vykresleni rastroveho obrazku postupne do vsech bitovych rovin.
; Horizontalni scrolling po stisku klavesy.
;
; preklad pomoci:
;     nasm -f bin -o vga.com vga_horizontal_scroll_1.asm
;
; nebo pouze:
;     nasm -o vga.com vga_horizontal_scroll_1.asm
 
 
;-----------------------------------------------------------------------------
 
; registry karty VGA
SEQUENCER_INDEX      equ 0x3c4
SEQUENCER_DATA       equ 0x3c5
CRTC_INDEX           equ 0x3d4
CRTC_DATA            equ 0x3d5
INPUT_STATUS         equ 0x3da
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
START_ADDRESS_HIGH   equ 0x0c   ; CRTC
START_ADDRESS_LOW    equ 0x0d   ; CRTC
 
; bitove masky
V_RETRACE            equ 0x08
 
; 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
 
        mov cx, 80          ; pocet bajtu(!), o ktere budeme scrollovat
        xor bx, bx          ; adresa zacatku vykreslovani
 
opak:
        inc bx              ; posun o jediny pixel
        call wait_sync      ; cekani na sync.
                            ; zmena adresy
        set_crtc_register START_ADDRESS_HIGH, bh
        set_crtc_register START_ADDRESS_LOW, bl
        loop opak
 
        wait_key            ; cekani na klavesu
        exit                ; navrat do DOSu
 
move_image_part:
        mov si, image       ; nyni DS:SI obsahuje adresu prvniho bajtu v obrazku
        add si, ax          ; offset pixelu
        mov di, 320*25      ; nyni ES:DI obsahuje adresu prvniho pixelu ve video RAM
                            ; kam budeme chtit provest vykreslovani
 
        mov cx, 320*200/4   ; pocet zapisovanych bajtu (=pixelu)
bitblt:
        lodsb               ; nacist bajt z obrazku
        add si, 3           ; celkove posun o 4 pixely v obrazku 
        stosb               ; ulozit do obrazove pameti
        loop bitblt         ; presunout CX pixelu
        ret
 
wait_sync:
        mov dx, INPUT_STATUS ; adresa stavoveho registru graficke karty CGA
wait_sync_end:
        in al, dx           ; precteni hodnoty stavoveho registru
        test al, V_RETRACE  ; odmaskovat priznak vertikalniho synchronizacniho pulsu
        jnz wait_sync_end   ; probiha - cekat na konec
wait_sync_start:
        in al, dx           ; precteni hodnoty stavoveho registru
        test al, V_RETRACE  ; odmaskovat priznak vertikalniho synchronizacniho pulsu
        jz wait_sync_start  ; neprobiha - cekat na zacatek
        ret                 ; ok - synchronizacni kurz probiha, lze zapisovat do pameti
 
; pridani binarnich dat s rastrovym obrazkem
image:
    incbin "image_320x200.bin"

15. Změna počtu pixelů na obrazových řádcích bez změny rozlišení

Aby byl horizontální scrolling realizován korektně (a navíc bez nutnosti přenosu obrazových dat z hlavní paměti do video paměti), musíme změnit logickou délku obrazových řádků, tedy vlastně rozdíl mezi adresou prvního pixelu na řádku n+1 a n. Tento rozdíl je uložen v CRTC registru OFFSET:

OFFSET               equ 0x13   ; CRTC

Poněkud problematické je, že hodnota uložená v tomto registru neodpovídá ve všech grafických režimech přímo offsetu. Výpočet konkrétní hodnoty závisí na požadovaném offsetu (logicky), ale i na grafickém režimu i na tom, jestli jsou bitové roviny zřetězeny či nikoli. Pokud budeme chtít v nezřetězeném režimu s 256 barvami používat řádky s logickou délkou 640 pixelů (tedy 160 pixelů v každé bitové rovině), musíme tuto hodnotu podělit 80

set_crtc_register OFFSET, 80                      ; 640 pixelu na radku (320 zobrazenych)

Nyní již bude horizontální scrolling probíhat podle předpokladu, protože obrazovka bude vlastně výřez z plochy dvojnásobně širší:

Obrázek 15: Horizontální scrolling po modifikaci délky obrazových řádků.

Obrázek 16: Horizontální scrolling po modifikaci délky obrazových řádků.

Poznámka: v tomto případě se ovšem logicky sníží počet dostupných obrazových řádků na polovinu. To například znamená, že nebude možné ho použít v režimech s rozlišením 320×480 ani 360×480 pixelů.

16. Šestý demonstrační příklad: horizontální scrolling při šířce řádků nastavených na 640 pixelů

Korektní (i když prozatím pouze hrubý) horizontální scrolling při nastavení logické šířky obrazových řádků na 640 pixelů, je realizován v dnešním šestém demonstračním příkladu, jehož úplný zdrojový kód vypadá následovně:

; Graficky rezim karty VGA s rozlisenim 320x400 pixelu.
; Vypnuti zretezeni bitovych rovin.
; Vykresleni rastroveho obrazku postupne do vsech bitovych rovin.
; Nastaveni "sirokych" obrazovych radku.
; Horizontalni scrolling po stisku klavesy.
;
; preklad pomoci:
;     nasm -f bin -o vga.com vga_horizontal_scroll_2.asm
;
; nebo pouze:
;     nasm -o vga.com vga_horizontal_scroll_2.asm
 
 
;-----------------------------------------------------------------------------
 
; registry karty VGA
SEQUENCER_INDEX      equ 0x3c4
SEQUENCER_DATA       equ 0x3c5
CRTC_INDEX           equ 0x3d4
CRTC_DATA            equ 0x3d5
INPUT_STATUS         equ 0x3da
BITPLANE_SELECTOR    equ 0x02
MEMORY_MODE_REGISTER equ 0x04   ; sekvencer
OFFSET               equ 0x13   ; CRTC
UNDERLINE_LOCATION   equ 0x14   ; CRTC
MODE_CONTROL         equ 0x17   ; CRTC
MAXIMUM_SCAN_LINE    equ 0x09   ; CRTC
START_ADDRESS_HIGH   equ 0x0c   ; CRTC
START_ADDRESS_LOW    equ 0x0d   ; CRTC
 
; bitove masky
V_RETRACE            equ 0x08
 
; 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
        set_crtc_register OFFSET, 80                      ; 640 pixelu na radku (320 zobrazenych)
 
        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
 
        mov cx, 80          ; pocet bajtu(!), o ktere budeme scrollovat
        xor bx, bx          ; adresa zacatku vykreslovani
 
opak:
        inc bx              ; posun o jediny pixel
        call wait_sync      ; cekani na sync.
                            ; zmena adresy
        set_crtc_register START_ADDRESS_HIGH, bh
        set_crtc_register START_ADDRESS_LOW, bl
        loop opak
 
        wait_key            ; cekani na klavesu
        exit                ; navrat do DOSu
 
move_image_part:
        mov si, image       ; nyni DS:SI obsahuje adresu prvniho bajtu v obrazku
        add si, ax          ; offset pixelu
        mov di, 320*50      ; nyni ES:DI obsahuje adresu prvniho pixelu ve video RAM
                            ; kam budeme chtit provest vykreslovani
        add di, 80          ; posun zacatku tak, aby obrazek zacinal "za rohem"
 
        mov dl, 200         ; pocitadlo radku
next_scan_line:
        mov cx, 320/4       ; pocet zapisovanych bajtu (=pixelu)
bitblt:
        lodsb               ; nacist bajt z obrazku
        add si, 3           ; celkove posun o 4 pixely v obrazku 
        stosb               ; ulozit do obrazove pameti
        loop bitblt         ; presunout CX pixelu
                            ; nyni je vykresleny jeden radek
        add di, 80          ; preskocit zbytek obrazoveho radku
        dec dl              ; dalsi radek?
        jnz next_scan_line  ; ok, dalsi radek
 
        ret
 
wait_sync:
        mov dx, INPUT_STATUS ; adresa stavoveho registru graficke karty CGA
wait_sync_end:
        in al, dx           ; precteni hodnoty stavoveho registru
        test al, V_RETRACE  ; odmaskovat priznak vertikalniho synchronizacniho pulsu
        jnz wait_sync_end   ; probiha - cekat na konec
wait_sync_start:
        in al, dx           ; precteni hodnoty stavoveho registru
        test al, V_RETRACE  ; odmaskovat priznak vertikalniho synchronizacniho pulsu
        jz wait_sync_start  ; neprobiha - cekat na zacatek
        ret                 ; ok - synchronizacni kurz probiha, lze zapisovat do pameti
 
; pridani binarnich dat s rastrovym obrazkem
image:
    incbin "image_320x200.bin"

17. Jemný horizontální scrolling

Nyní nám zbývá realizovat poslední krok, a to konkrétně doplnit hrubý horizontální scrolling (o čtyři pixely) o jemný scrolling realizující posun o jeden až tři pixely. I tento trik grafická karta VGA podporuje, i když registr ovládající jemný skrolling je poněkud nelogicky umístěn do sekce s ovládáním atributového řadiče (evidentně se tento posun interně provádí až v závěrečné fázi generování obrazu). Jedná se o registr s indexem 0×13, ovšem my již víme, že aby došlo ke změně, je nutné k indexu registru ATC přičíst hodnotu 0×20, takže nový „index“ bude mít hodnotu 0×33. Zapisovat lze hodnoty 0 až 15, protože se využívají jen spodní čtyři bity tohoto registru (proto je nutné po posunu o 4 pixely provést hrubý scrolling atd.):

fine_scroll:
        mov dx, ATTRIBUTE_CONTROLLER
        mov al, 0x33        ; PEL panning
        out dx, al          ; index registru
        mov al, ah
        out dx, al          ; hodnota registru
        ret

Kombinace hrubého a jemného horizontálního scrollingu vypadá například takto:

opak:
        mov ah, 0           ; jemny posun
fine_scroll_opak:
        call wait_sync      ; cekani na sync.
        call fine_scroll    ; jemny posun o AH pixelu
        inc ah
        cmp ah, 8           ; jak se posuneme o 8, muzeme jit o bajt dale
        jne fine_scroll_opak
 
        inc bx              ; posun o jediny pixel - ve skutecnosti posun o 4 pixely celkem
                            ; zmena adresy
        set_crtc_register START_ADDRESS_HIGH, bh
        set_crtc_register START_ADDRESS_LOW, bl
        loop opak

Je zde ovšem ještě jeden problém, a to konkrétně dělení hodnoty jemného scrollingu dvěma v některých grafických režimech. Konkrétně tedy budeme muset provést jemný scrolling o 0 až 7 „půlpixelů“ a poté provést hrubý scrolling (nebo raději provést jemný posun o sudé hodnoty, protože se uvádí, že posun o liché hodnoty může vést k poškození obsahu obrazovky – to jsem ovšem nikdy na reálném HW neviděl). Nicméně oprava příkladu by měla být snadná (zdvojit instrukci INC).

Obrázek 17: Jemný horizontální scrolling.

Obrázek 18: Jemný horizontální scrolling.

Obrázek 19: Jemný horizontální scrolling.

CS24 tip temata

18. Sedmý demonstrační příklad: jemný horizontální scrolling

Jemný horizontální scrolling, pochopitelně kombinovaný s hrubým scrollingem, je realizován v dnešním sedmém a současně i posledním demonstračním příkladu, jehož úplný zdrojový kód je vypsán pod tímto odstavcem:

; Graficky rezim karty VGA s rozlisenim 320x400 pixelu.
; Vypnuti zretezeni bitovych rovin.
; Vykresleni rastroveho obrazku postupne do vsech bitovych rovin.
; Nastaveni "sirokych" obrazovych radku.
; Jemny horizontalni scrolling po stisku klavesy.
;
; preklad pomoci:
;     nasm -f bin -o vga.com vga_horizontal_scroll_3.asm
;
; nebo pouze:
;     nasm -o vga.com vga_horizontal_scroll_3.asm
 
 
;-----------------------------------------------------------------------------
 
; registry karty VGA
ATTRIBUTE_CONTROLLER equ 0x3c0
SEQUENCER_INDEX      equ 0x3c4
SEQUENCER_DATA       equ 0x3c5
CRTC_INDEX           equ 0x3d4
CRTC_DATA            equ 0x3d5
INPUT_STATUS         equ 0x3da
BITPLANE_SELECTOR    equ 0x02
MEMORY_MODE_REGISTER equ 0x04   ; sekvencer
OFFSET               equ 0x13   ; CRTC
UNDERLINE_LOCATION   equ 0x14   ; CRTC
MODE_CONTROL         equ 0x17   ; CRTC
MAXIMUM_SCAN_LINE    equ 0x09   ; CRTC
START_ADDRESS_HIGH   equ 0x0c   ; CRTC
START_ADDRESS_LOW    equ 0x0d   ; CRTC
 
; bitove masky
V_RETRACE            equ 0x08
 
; 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
        set_crtc_register OFFSET, 80                      ; 640 pixelu na radku (320 zobrazenych)
 
        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
 
        mov cx, 80          ; pocet bajtu(!), o ktere budeme scrollovat
        xor bx, bx          ; adresa zacatku vykreslovani
 
opak:
        mov ah, 0           ; jemny posun
fine_scroll_opak:
        call wait_sync      ; cekani na sync.
        call fine_scroll    ; jemny posun o AH pixelu
        inc ah
        cmp ah, 8           ; jak se posuneme o 8, muzeme jit o bajt dale
        jne fine_scroll_opak
 
        inc bx              ; posun o jediny pixel
                            ; zmena adresy
        set_crtc_register START_ADDRESS_HIGH, bh
        set_crtc_register START_ADDRESS_LOW, bl
        loop opak
 
        wait_key            ; cekani na klavesu
        exit                ; navrat do DOSu
 
fine_scroll:
        mov dx, ATTRIBUTE_CONTROLLER
        mov al, 0x33        ; PEL panning
        out dx, al          ; index registru
        mov al, ah
        out dx, al          ; hodnota registru
        ret
 
move_image_part:
        mov si, image       ; nyni DS:SI obsahuje adresu prvniho bajtu v obrazku
        add si, ax          ; offset pixelu
        mov di, 320*50      ; nyni ES:DI obsahuje adresu prvniho pixelu ve video RAM
                            ; kam budeme chtit provest vykreslovani
        add di, 80          ; posun zacatku tak, aby obrazek zacinal "za rohem"
 
        mov dl, 200         ; pocitadlo radku
next_scan_line:
        mov cx, 320/4       ; pocet zapisovanych bajtu (=pixelu)
bitblt:
        lodsb               ; nacist bajt z obrazku
        add si, 3           ; celkove posun o 4 pixely v obrazku 
        stosb               ; ulozit do obrazove pameti
        loop bitblt         ; presunout CX pixelu
                            ; nyni je vykresleny jeden radek
        add di, 80          ; preskocit zbytek obrazoveho radku
        dec dl              ; dalsi radek?
        jnz next_scan_line  ; ok, dalsi radek
 
        ret
 
wait_sync:
        mov dx, INPUT_STATUS ; adresa stavoveho registru graficke karty CGA
wait_sync_end:
        in al, dx           ; precteni hodnoty stavoveho registru
        test al, V_RETRACE  ; odmaskovat priznak vertikalniho synchronizacniho pulsu
        jnz wait_sync_end   ; probiha - cekat na konec
wait_sync_start:
        in al, dx           ; precteni hodnoty stavoveho registru
        test al, V_RETRACE  ; odmaskovat priznak vertikalniho synchronizacniho pulsu
        jz wait_sync_start  ; neprobiha - cekat na zacatek
        ret                 ; ok - synchronizacni kurz probiha, lze zapisovat do pameti
 
; pridani binarnich dat s rastrovym obrazkem
image:
    incbin "image_320x200.bin"

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
       
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

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
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.