Obsah
1. Grafické operace přímo podporované čipy karty VGA
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ů
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
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
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:
- Zápis většího množství pixelů se stejnou barvou (díky bitovým rovinám)
- Blokové přenosy dat mezi částmi grafické paměti bez nutnosti jejich čtení/zápisu do CPU
- Jemný vertikální scrolling obrazovky po jednotlivých obrazových řádcích
- Hrubý i jemný horizontální scrolling obrazovky po bajtech nebo po pixelech
- Takzvaný režim split screen, kdy jsou dvě části obrazovky uloženy na odlišných adresách a jedna část podporuje scrolling
- Podpora pro double i tripple buffering umožňující vykreslování grafické scény na pozadí
- 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
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).
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ů:
- 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ů.
- 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ů.
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.
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
- The Intel 8088 Architecture and Instruction Set
https://people.ece.ubc.ca/~edc/464/lectures/lec4.pdf - x86 Opcode Structure and Instruction Overview
https://pnx.tf/files/x86_opcode_structure_and_instruction_overview.pdf - x86 instruction listings (Wikipedia)
https://en.wikipedia.org/wiki/X86_instruction_listings - x86 assembly language (Wikipedia)
https://en.wikipedia.org/wiki/X86_assembly_language - Intel Assembler (Cheat sheet)
http://www.jegerlehner.ch/intel/IntelCodeTable.pdf - 25 Microchips That Shook the World
https://spectrum.ieee.org/tech-history/silicon-revolution/25-microchips-that-shook-the-world - Chip Hall of Fame: MOS Technology 6502 Microprocessor
https://spectrum.ieee.org/tech-history/silicon-revolution/chip-hall-of-fame-mos-technology-6502-microprocessor - Chip Hall of Fame: Intel 8088 Microprocessor
https://spectrum.ieee.org/tech-history/silicon-revolution/chip-hall-of-fame-intel-8088-microprocessor - Jak se zrodil procesor?
https://www.root.cz/clanky/jak-se-zrodil-procesor/ - Apple II History Home
http://apple2history.org/ - The 8086/8088 Primer
https://www.stevemorse.org/8086/index.html - flat assembler: Assembly language resources
https://flatassembler.net/ - FASM na Wikipedii
https://en.wikipedia.org/wiki/FASM - Fresh IDE FASM inside
https://fresh.flatassembler.net/ - MS-DOS Version 4.0 Programmer's Reference
https://www.pcjs.org/documents/books/mspl13/msdos/dosref40/ - INT 21 – DOS Function Dispatcher (DOS)
https://www.stanislavs.org/helppc/int21.html - DOS API (Wikipedia)
https://en.wikipedia.org/wiki/DOS_API - Bit banging
https://en.wikipedia.org/wiki/Bit_banging - IBM Basic assembly language and successors (Wikipedia)
https://en.wikipedia.org/wiki/IBM_Basic_assembly_language_and_successors - X86 Assembly/Bootloaders
https://en.wikibooks.org/wiki/X86_Assembly/Bootloaders - Počátky grafiky na PC: grafické karty CGA a Hercules
https://www.root.cz/clanky/pocatky-grafiky-na-pc-graficke-karty-cga-a-hercules/ - 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/ - Karta EGA: první použitelná barevná grafika na PC
https://www.root.cz/clanky/karta-ega-prvni-pouzitelna-barevna-grafika-na-pc/ - RGB Classic Games
https://www.classicdosgames.com/ - Turbo Assembler (Wikipedia)
https://en.wikipedia.org/wiki/Turbo_Assembler - Microsoft Macro Assembler
https://en.wikipedia.org/wiki/Microsoft_Macro_Assembler - IBM Personal Computer (Wikipedia)
https://en.wikipedia.org/wiki/IBM_Personal_Computer - Intel 8251
https://en.wikipedia.org/wiki/Intel_8251 - Intel 8253
https://en.wikipedia.org/wiki/Intel_8253 - Intel 8255
https://en.wikipedia.org/wiki/Intel_8255 - Intel 8257
https://en.wikipedia.org/wiki/Intel_8257 - Intel 8259
https://en.wikipedia.org/wiki/Intel_8259 - Support/peripheral/other chips – 6800 family
http://www.cpu-world.com/Support/6800.html - Motorola 6845
http://en.wikipedia.org/wiki/Motorola_6845 - The 6845 Cathode Ray Tube Controller (CRTC)
http://www.tinyvga.com/6845 - CRTC operation
http://www.6502.org/users/andre/hwinfo/crtc/crtc.html - 6845 – Motorola CRT Controller
https://stanislavs.org/helppc/6845.html - The 6845 Cathode Ray Tube Controller (CRTC)
http://www.tinyvga.com/6845 - Motorola 6845 and bitwise graphics
https://retrocomputing.stackexchange.com/questions/10996/motorola-6845-and-bitwise-graphics - IBM Monochrome Display Adapter
http://en.wikipedia.org/wiki/Monochrome_Display_Adapter - Color Graphics Adapter
http://en.wikipedia.org/wiki/Color_Graphics_Adapter - Color Graphics Adapter and the Brown color in IBM 5153 Color Display
https://www.aceinnova.com/en/electronics/cga-and-the-brown-color-in-ibm-5153-color-display/ - The Modern Retrocomputer: An Arduino Driven 6845 CRT Controller
https://hackaday.com/2017/05/14/the-modern-retrocomputer-an-arduino-driven-6845-crt-controller/ - flat assembler: Assembly language resources
https://flatassembler.net/ - FASM na Wikipedii
https://en.wikipedia.org/wiki/FASM - Fresh IDE FASM inside
https://fresh.flatassembler.net/ - MS-DOS Version 4.0 Programmer's Reference
https://www.pcjs.org/documents/books/mspl13/msdos/dosref40/ - INT 21 – DOS Function Dispatcher (DOS)
https://www.stanislavs.org/helppc/int21.html - DOS API (Wikipedia)
https://en.wikipedia.org/wiki/DOS_API - IBM Basic assembly language and successors (Wikipedia)
https://en.wikipedia.org/wiki/IBM_Basic_assembly_language_and_successors - X86 Assembly/Arithmetic
https://en.wikibooks.org/wiki/X86_Assembly/Arithmetic - Art of Assembly – Arithmetic Instructions
http://oopweb.com/Assembly/Documents/ArtOfAssembly/Volume/Chapter6/CH06–2.html - ASM Flags
http://www.cavestory.org/guides/csasm/guide/asm_flags.html - Status Register
https://en.wikipedia.org/wiki/Status_register - Linux assemblers: A comparison of GAS and NASM
http://www.ibm.com/developerworks/library/l-gas-nasm/index.html - Programovani v assembleru na OS Linux
http://www.cs.vsb.cz/grygarek/asm/asmlinux.html - Is it worthwhile to learn x86 assembly language today?
https://www.quora.com/Is-it-worthwhile-to-learn-x86-assembly-language-today?share=1 - Why Learn Assembly Language?
http://www.codeproject.com/Articles/89460/Why-Learn-Assembly-Language - Is Assembly still relevant?
http://programmers.stackexchange.com/questions/95836/is-assembly-still-relevant - Why Learning Assembly Language Is Still a Good Idea
http://www.onlamp.com/pub/a/onlamp/2004/05/06/writegreatcode.html - Assembly language today
http://beust.com/weblog/2004/06/23/assembly-language-today/ - Assembler: Význam assembleru dnes
http://www.builder.cz/rubriky/assembler/vyznam-assembleru-dnes-155960cz - Programming from the Ground Up Book – Summary
http://savannah.nongnu.org/projects/pgubook/ - DOSBox
https://www.dosbox.com/ - The C Programming Language
https://en.wikipedia.org/wiki/The_C_Programming_Language - Hercules Graphics Card (HCG)
https://en.wikipedia.org/wiki/Hercules_Graphics_Card - Complete 8086 instruction set
https://content.ctcd.edu/courses/cosc2325/m22/docs/emu8086ins.pdf - Complete 8086 instruction set
https://yassinebridi.github.io/asm-docs/8086_instruction_set.html - 8088 MPH by Hornet + CRTC + DESiRE (final version)
https://www.youtube.com/watch?v=hNRO7lno_DM - Area 5150 by CRTC & Hornet (Party Version) / IBM PC+CGA Demo, Hardware Capture
https://www.youtube.com/watch?v=fWDxdoRTZPc - 80×86 Integer Instruction Set Timings (8088 – Pentium)
http://aturing.umcs.maine.edu/~meadow/courses/cos335/80×86-Integer-Instruction-Set-Clocks.pdf - Colour Graphics Adapter: Notes
https://www.seasip.info/VintagePC/cga.html - Restoring A Vintage CGA Card With Homebrew HASL
https://hackaday.com/2024/06/12/restoring-a-vintage-cga-card-with-homebrew-hasl/ - Demoing An 8088
https://hackaday.com/2015/04/10/demoing-an-8088/ - Video Memory Layouts
http://www.techhelpmanual.com/89-video_memory_layouts.html - Screen Attributes
http://www.techhelpmanual.com/87-screen_attributes.html - IBM PC Family – BIOS Video Modes
https://www.minuszerodegrees.net/video/bios_video_modes.htm - EGA Functions
https://cosmodoc.org/topics/ega-functions/#the-hierarchy-of-the-ega - 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/ - How 16 colors saved PC gaming – the story of EGA graphics
https://www.custompc.com/retro-tech/ega-graphics - List of 16-bit computer color palettes
https://en.wikipedia.org/wiki/List_of16-bit_computer_color_palettes - Why were those colors chosen to be the default palette for 256-color VGA?
https://retrocomputing.stackexchange.com/questions/27994/why-were-those-colors-chosen-to-be-the-default-palette-for-256-color-vga - VGA Color Palettes
https://www.fountainware.com/EXPL/vga_color_palettes.htm - Hardware Level VGA and SVGA Video Programming Information Page
http://www.osdever.net/FreeVGA/vga/vga.htm - Hardware Level VGA and SVGA Video Programming Information Page – sequencer
http://www.osdever.net/FreeVGA/vga/seqreg.htm - VGA Basics
http://www.brackeen.com/vga/basics.html - Introduction to VGA Mode ‚X‘
https://web.archive.org/web/20160414072210/http://fly.srk.fer.hr/GDM/articles/vgamodex/vgamx1.html - VGA Mode-X
https://web.archive.org/web/20070123192523/http://www.gamedev.net/reference/articles/article356.asp - Mode-X: 256-Color VGA Magic
https://downloads.gamedev.net/pdf/gpbb/gpbb47.pdf - Instruction Format in 8086 Microprocessor
https://www.includehelp.com/embedded-system/instruction-format-in-8086-microprocessor.aspx