Obsah
1. Grafická karta VGA a slavný režim X (X-mode)
2. Praktická nutnost použití nestandardních grafických režimů
4. Nastavení komparátorů uložených v registrech CRTC
5. Význam komparátorů pro čítač řádků
6. Programový kód pro nastavení registrů CRTC
7. Ostatní registry karty VGA, které je zapotřebí nastavit
8. Ucelený seznam všech změn, které je nutné nakonfigurovat
9. Programové přepnutí do režimu X
10. Přístup k bitovým rovinám, scrolling a další možnosti režimu X
11. Úplný zdrojový kód dnešního prvního demonstračního příkladu: demo využívající režim X
12. Modularizace programu v NASMu bez použití linkeru
14. Zamezení vložení modulu vícekrát do hlavního programu při překladu
15. Modul s makry pro I/O operace
16. Symboly, makra a subrutiny pro zjednodušení programování grafické karty VGA
17. Přepis demonstračního příkladu tak, aby se využívaly moduly
18. Repositář s demonstračními příklady
1. Grafická karta VGA a slavný režim X (X-mode)
V dnešní části seriálu o vývoji her a grafických dem pro platformu IBM PC s DOSem dokončíme sekci věnovanou programování grafické karty VGA. Připomeňme si, že tato karta nabízela tři nové standardní (resp. standardizované) grafické režimy. První dva režimy označované 11h a 12h (podle jejich čísel v BIOSu) měly rozlišení 640×480 pixelů a buď dvě barvy nebo 16 barev (podle dostupné kapacity video paměti). A třetí režim označovaný 13h nabízel rozlišení 320×200 pixelů, ovšem dokázal současně zobrazit 256 barev, navíc tak, že pro nastavení barvové palety byl přímo využit DAC a nikoli dvojí mapování palety. Poměrně záhy po uvedení VGA na trh se ustálila konfigurace s 256 kB video paměti, takže režim 11h postrádal význam. A současně byly režimy karty VGA posledními režimy oficiálně přidanými do PC BIOSu – poté již nastala éra různých nestandardních režimů, do čehož již společnost IBM zasahovala spíše jen okrajově.
Programátoři tedy mohli využívat tyto standardní režimy (do tabulky jsem přidal i Hercules, který nikdy nebyl přidán do standardního BIOSu):
Číslo (AL) | Karty | Monitory | Typ | Rozlišení | Barvy | Segment | |
---|---|---|---|---|---|---|---|
00 | CGA, EGA | kompozitní | text | 40×25 | mono, 16 barev | 0×b800 | |
01 | CGA, EGA | kompozitní, RGBI, EGA | text | 40×25 | mono, 16 barev | 0×b800 | |
02 | CGA, EGA | kompozitní | text | 80×25 | mono, 16 barev | 0×b800 | |
03 | CGA, EGA | kompozitní, RGBI, EGA | text | 80×25 | mono, 16 barev | 0×b800 | |
04 | CGA, EGA | kompozitní, RGBI, EGA | grafika | 320×200 | 4 | 0×b800 | |
05 | CGA, EGA | kompozitní | grafika | 320×200 | 4 | 0×b800 | |
06 | CGA, EGA | kompozitní, RGBI, EGA | grafika | 640×200 | 2 | 0×b800 | |
07 | MDA, EGA | TTL mono (MDA) | text | 80×25 | mono+intenzita | 0×b000 | |
N/A | Hercules | TTL mono (MDA) | grafika | 720×348 | mono | 0×b000 nebo 0×b800 | |
0d | EGA | EGA | grafika | 320×200 | 16 | 0×a000 | |
0e | EGA | EGA | grafika | 640×200 | 16 | 0×a000 | |
0f | EGA | TTL mono (MDA), EGA | grafika | 640×350 | 3 (BW) | 0×a000 | |
10 | EGA | EGA | grafika | 640×350 | 4 nebo 16 | 0×a000 | |
11 | VGA | VGA (analog) | grafika | 640×480 | 2 | 0×a000 | |
12 | VGA | VGA (analog) | grafika | 640×480 | 16 | 0×a000 | |
13 | VGA | VGA (analog) | grafika | 320×200 | 256 | 0×a000 |
Obrázek 1: Režim X použitý ve hře Epic Pinball (vůbec pinbally často na VGA používaly různé triky).
2. Praktická nutnost použití nestandardních grafických režimů
Grafická karta VGA navíc umožňovala velmi snadno realizovat i následující grafické operace, které byly popsány minule:
- 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)
Ovšem současně existovala mnohá omezení:
- Double a tripple buffering nedává pro standardní grafické režimy smysl
- Do značné míry se to týká screen-splittingu a horizontálního i vertikálního scrollingu v režimu 13h
- Režim 13h nemá čtvercové pixely, což nevadí pro statické obrázky (ty lze předpřipravit), ale hlavně u 3D algoritmů
Z tohoto důvodu programátoři hledali (a nacházeli) způsoby přepnutí VGA do nestandardních grafických režimů, které by byly kompatibilní s původními monitory s pevnými frekvencemi, ovšem současně by využily všechny výše zmíněné možnosti a jako třešničku na dortu by měly čtvercové pixely. Výsledkem těchto snah byl režim X (X-mode, Mode-X), který se stal nepsaným standardem.
Obrázek 2: Režim X použitý ve hře Pinball Illusions.
3. Režim X
Shrňme si tedy, co se skrývá pod označením režim X. Jedná se o grafický režim odvozený od standardního režimu 13h, který byl ovšem modifikován, a to hned v několika oblastech. Zejména došlo k vypnutí zřetězení bitových rovin, takže bylo možné přistupovat k celým 256 kB video paměti a umožnilo to realizaci scrollingu i double či tripple bufferingu. Dále se změnil počet obrazových řádků z 200 na 240, což vlastně vychází ze standardního režimu 640×480, ovšem se zapnutým „zdvojováním“ obrazových řádků (každý řádek je vykreslen dvakrát a má tedy dvojnásobnou výšku). Přepnutí počtu obrazových řádků je provedeno takovým způsobem, aby byl tento grafický režim podporován i na původních monitorech s pevnými frekvencemi (velmi zjednodušeně řečeno tyto monitory dokázaly zobrazit 350, 400 nebo 480 obrazových řádků, popř. poloviční hodnoty, tedy 175, 200 a 240 řádků).
Obrázek 3: Režim X (a všesměrový scrolling atd.) nalezneme i ve známé hře The Lost Vikings.
4. Nastavení komparátorů uložených v registrech CRTC
Vzhledem k tomu, že se v režimu X mění vertikální rozlišení, je nutné přenastavit i CRTC registry, které se týkají čítače řádků. Podívejme se, o které registry se jedná a jakou mají mít hodnotu. Uvedeny jsou i hodnoty těchto registrů pro režim 12h (640×480) i 13h (320×200), aby bylo patrné, že režim X je vlastně mixem těchto dvou režimů – a čím více registrů má totožnou hodnotu, tím je režim „kompatibilnější“:
Registr | Index registru | Režim 12h | Režim 13h | Režim X |
---|---|---|---|---|
Vertical Total | 0×06 | 0×0B | 0×BF | 0×0D |
Overflow Register | 0×07 | 0×3E | 0×1F | 0×3E |
Maximum Scan Line | 0×09 | 0×40 | 0×41 | 0×41 |
Vertical Retrace Start | 0×10 | 0×EA | 0×9C | 0×EA |
Vertical Retrace End | 0×11 | 0×8C | 0×8E | 0×AC |
Vertical Display End | 0×12 | 0×DF | 0×8F | 0×DF |
Underline Location | 0×14 | 0×00 | 0×40 | 0×00 |
Vertical Blank Start | 0×15 | 0×E7 | 0×96 | 0×E7 |
Vertical Blank End | 0×16 | 0×04 | 0×B9 | 0×06 |
Mode Control | 0×17 | 0×E3 | 0×A3 | 0×E3 |
Obrázek 4: Režim X (a všesměrový scrolling atd.) nalezneme i ve známé hře The Lost Vikings.
5. Význam komparátorů pro čítač řádků
Na způsob zobrazení obrazových řádků mají vliv komparátory dostupné přes registry CRTC. Těchto komparátorů je několik. Vstupem je přitom hodinový signál vybíraný bitem Clock Select. U karet VGA může mít hodinový signál frekvenci buď 25 MHz (přesněji 25,175 MHz) nebo 28 MHz, přičemž pro režimy s horizontálním rozlišení 720 nebo 360 pixelů se používá 28 MHz, jinak 25 MHz. Z této hodnoty se vypočítá řádková frekvence podle vztahu:
f_hor = f_clock / počet všech bodů na řádku
přičemž počet všech pixelů je vždy vyšší, než počet zobrazených pixelů (což nás ale nyní nemusí trápit). Z řádkové frekvence a počtu všech obrazových řádků (i neviditelných) můžeme odvodit vertikální frekvenci, tj. počet snímků:
f_ver = f_hor / počet všech obrazových řádků
Konkrétní hodnoty pro režim X s 800 body na řádku (zobrazeno 640 bodů, děleno dvěma nám dá 320 viditelných pixelů) a 525 obrazovými řádky (zobrazeno 480 řádků, opět děleno dvěma nám dá 240 viditelných logických řádků):
f_clock = 25,175 Mhz f_hor = f_clock / 800 = 31,468 kHz f_ver = f_hor / 525 = 59,94 Hz což zaokrouhlujeme na 60 Hz
Nás nyní bude zajímat především počitadlo obrazových řádků, které je interně zvyšováno kartou VGA ve chvíli, kdy se napočítají všechny pixely na řádku (včetně pixelů neviditelných – okrajů, návratu paprsku atd.)
Počitadlo řádků dosahuje hodnot 1 až 525 a porovnává se s obsahem registrů Vertical Total, Vertical Retrace Start/End, Vertical Display End a Vertical Blank Start/End. Konkrétně pro režim X použijeme tyto hodnoty:
Komparátor | Hodnota |
---|---|
Vertical Total | 525 |
Vertical Display End | 479 |
Vertical Blank Start | 487 |
Vertical Retrace Start | 490 |
Vertical Blank End | 6 (jen část periody od začátku) |
Vertical Retrace End | 12 (dtto) |
Počet zobrazených (viditelných) řádků je určen registrem Vertical Display End; jedná se o 1+479=480 řádků, přičemž interně dochází k načtení barev pro dva po sobě jdoucí řádky ze stejné adresy (což je ono již zmíněné zdvojování řádků), takže logicky máme k dispozici 240 řádků. Na obrazovém řádku 487 se zapíná vertical blanking (zákaz posílání video signálu), po němž na řádku 490 následuje návrat paprsku na začátek další obrazovky (a tím pádem VSync). Celkově počitadlo řádků čítá od 0 do 525.
6. Programový kód pro nastavení registrů CRTC
Podívejme se nyní na způsob nastavení registrů CRTC takovým způsobem, aby se provedlo přepnutí komparátorů čítače řádků pro režim X. Nejprve pochopitelně specifikujeme I/O port pro CRTC registry karty VGA:
CRTC_INDEX equ 0x3d4
Následně si uložíme indexy a hodnoty CRTC registrů do jednoduché tabulky:
crtc_values: dw 00d06h ; Vertical Total dw 03e07h ; Overflow Register dw 04109h ; Cell Height (teoreticky nemusime menit) dw 0ea10h ; Vertical Retrace Start dw 0ac11h ; Vertical Retrace End dw 0df12h ; Vertical Display End dw 00014h ; Underline Location dw 0e715h ; Vertical Blank Start dw 00616h ; Vertical Blank End dw 0e317h ; Mode Control
Následně pouze budeme iterovat touto tabulkou a budeme posílat indexy a hodnoty na dva po sobě jdoucí I/O porty. Pro tento účel použijeme instrukci out:
mov dx, CRTC_INDEX ; budou se zapisovat hodnoty CRTC registru cld ; smer prenosu (pro jistotu) mov si, crtc_values ; tabulka s hodnotami CRTC registru mov cx, 10 ; velikost tabulky s hodnotami CRTC registru set_crtc: lodsw ; nacteni dvojice: index registru + hodnota registru out dx, ax ; zapis do zvoleneho CRTC registru loop set_crtc ; provest vsech 10 zapisu
7. Ostatní registry karty VGA, které je zapotřebí nastavit
Pro přepnutí do režimu X je ve skutečnosti nutné manipulovat ještě s několika registry (kromě již zmíněných registrů CRTC), tedy grafického řadiče). Tato manipulace probíhá buď explicitně (a tedy ji uvidíme ve zdrojovém kódu) nebo si můžeme ulehčit práci a nejdříve se přepnout do standardního režimu 13h, tedy do režimu s rozlišením 320×200 pixelů s 256 barvami. V první řadě se jedná o registry řadiče atributů (attribute controller), konkrétně registrů s indexy 0×10 až 0×14. Ty mají v režimu 13h i v režimu X naprosto stejnou hodnotu (odlišnou od výchozího textového režimu):
Jméno registru | I/O port | Index registru |
---|---|---|
Mode Control | 0×3C0 | 0×10 |
Overscan Register | 0×3C0 | 0×11 |
Color Plane Enable | 0×3C0 | 0×12 |
Horizontal Panning | 0×3C0 | 0×13 |
Color Select | 0×3C0 | 0×14 |
Naprosto shodné jsou i obsahy dvou registrů pro nastavení grafického režimu. Tyto registry jsou dostupné na I/O portu 0×3ce s indexy 0×05 a 0×06:
Jméno registru | I/O port | Index registru |
---|---|---|
Mode Register | 0×3CE | 0×05 |
Miscellaneous Register | 0×3CE | 0×06 |
Totéž platí i pro obsah dvou řídicích registrů sekvencéru, ovšem s tím dodatkem, že obsah registru Memory Mode bude jiný kvůli tomu, že režim X nepoužívá zřetězené bitové roviny:
Jméno registru | I/O port | Index registru |
---|---|---|
Clock Mode Register | 0×3C4 | 0×01 |
Character select | 0×3C4 | 0×03 |
Memory Mode Register | 0×3C4 | 0×04 |
A konečně změny nalezneme v obsahu registru Miscellaneous Output, v němž jsou specifikovány (kromě dalších věcí) i polarity horizontální a vertikální synchronizace. Podle polarity dokázaly starší monitory s fixní frekvencí rozhodnout o počtu řádků i o řádkové frekvenci:
Jméno registru | I/O port | |
---|---|---|
Miscellaneous Output | 0×3C2 | N/A |
8. Ucelený seznam všech změn, které je nutné nakonfigurovat
Změn v konfiguraci grafické karty VGA je skutečně hodně, takže si je shrňme do ucelené tabulky, v níž jsou porovnány hodnoty nejdůležitějších řídicích registrů pro standardní režim 13h a režim X:
Jméno registru | I/O port | Index registru | Hodnota pro 13h | Hodnota pro Mode-X | |
---|---|---|---|---|---|
Mode Control | 0×3C0 | 0×10 | 0×41 | 0×41 | |
Overscan Register | 0×3C0 | 0×11 | 0×00 | 0×00 | |
Color Plane Enable | 0×3C0 | 0×12 | 0×0F | 0×0F | |
Horizontal Panning | 0×3C0 | 0×13 | 0×00 | 0×00 | |
Color Select | 0×3C0 | 0×14 | 0×00 | 0×00 | |
Miscellaneous Output | 0×3C2 | N/A | 0×63 | 0×E3 | |
Clock Mode Register | 0×3C4 | 0×01 | 0×01 | 0×01 | |
Character select | 0×3C4 | 0×03 | 0×00 | 0×00 | |
Memory Mode Register | 0×3C4 | 0×04 | 0×0E | 0×06 | |
Mode Register | 0×3CE | 0×05 | 0×40 | 0×40 | |
Miscellaneous Register | 0×3CE | 0×06 | 0×05 | 0×05 | |
Horizontal Total | 0×3D4 | 0×00 | 0×5F | 0×5F | |
Horizontal Display End | 0×3D4 | 0×01 | 0×4F | 0×4F | |
Horizontal Blank Start | 0×3D4 | 0×02 | 0×50 | 0×50 | |
Horizontal Blank End | 0×3D4 | 0×03 | 0×82 | 0×82 | |
Horizontal RetraStart | 0×3D4 | 0×04 | 0×54 | 0×54 | |
Horizontal Retrace End | 0×3D4 | 0×05 | 0×80 | 0×80 | |
Vertical Total | 0×3D4 | 0×06 | 0×BF | 0×0D | |
Overflow Register | 0×3D4 | 0×07 | 0×1F | 0×3E | |
Preset row scan | 0×3D4 | 0×08 | 0×00 | 0×00 | |
Maximum Scan Line | 0×3D4 | 0×09 | 0×41 | 0×41 | |
Vertical Retrace Start | 0×3D4 | 0×10 | 0×9C | 0×EA | |
Vertical Retrace End | 0×3D4 | 0×11 | 0×8E | 0×AC | |
Vertical Display End | 0×3D4 | 0×12 | 0×8F | 0×DF | |
Logical Width | 0×3D4 | 0×13 | 0×28 | 0×28 | |
Underline Location | 0×3D4 | 0×14 | 0×40 | 0×00 | |
Vertical Blank Start | 0×3D4 | 0×15 | 0×96 | 0×E7 | |
Vertical Blank End | 0×3D4 | 0×16 | 0×B9 | 0×06 | |
Mode Control | 0×3D4 | 0×17 | 0×A3 | 0×E3 |
9. Programové přepnutí do režimu X
Kroků nutných pro přepnutí do režimu X je hned několik, takže si je pojďme postupně popsat. Nejdříve se přepneme do standardního režimu 13h (320×200), což nám zjednoduší práci. Použijeme k tomu připravené makro:
gfx_mode 0x13 ; nastaveni rezimu 320x200 s 256 barvami
Dále vypneme zřetězení bitových rovin, což už taktéž známe:
; 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
Vypneme sekvencér (nastavíme reset), takže vlastně zakážeme video signál:
; prepnuti do 320x240 mov dx, SEQUENCER_INDEX mov ax, 0x100 ; synchronni reset (bit cislo 1 je vynulovan) out dx, ax
Přepneme hodinový signál používaný pro čtení pixelů na 25 MHz, což interně změní obrazovou frekvenci na 60 Hz a nastaví polaritu synchronizačního signálu pro monitory s fixními frekvencemi:
mov dx, MISC_REGISTER mov al, 0xe3 out dx, al ; hodiny 25 MHz obrazova frekvence 60 Hz (nastaveni polarity syncu)
Opět povolíme sekvencér (video signál):
mov dx, SEQUENCER_INDEX mov ax, 0x300 ; restart sekvenceru (oba resety jsou zakazane) out dx, ax
Sedmý bit registru Vertical Retrace End slouží jako zámek pro přístup k mnoha dalším registrům CRTC, aby se omylem nepoškodil monitor, pokud program chybně přistoupí k CRTC. Tento zámek nyní odemkneme, protože chceme zničit monitor^W^W nastavit režim X:
mov dx, CRTC_INDEX mov al, 0x11 ; Vertical Retrace End registr out dx, al inc dx in al, dx ; cteni hodnoty registru and al, 0x7f ; vypnout write protect bit (sedmi bit) out dx, al ; nyni lze zapisovat do jakehokoli CRTC registru
Následuje již známá část – nastavení komparátorů uložených v registrech CRTC:
mov dx, CRTC_INDEX ; budou se zapisovat hodnoty CRTC registru cld ; smer prenosu (pro jistotu) mov si, crtc_values ; tabulka s hodnotami CRTC registru mov cx, 10 ; velikost tabulky s hodnotami CRTC registru set_crtc: lodsw ; nacteni dvojice: index registru + hodnota registru out dx, ax ; zapis do zvoleneho CRTC registru loop set_crtc ; provest vsech 10 zapisu
10. Přístup k bitovým rovinám, scrolling a další možnosti režimu X
V režimu X můžeme použít všechny triky, které byly popsány minule. V dnešním prvním demonstračním příkladu si ukážeme tuto funkcionalitu:
- Nastavení režimu X (logicky)
- Nastavení barvové palety přes DAC
- Výběr bitové roviny nebo rovin pro zápis na obrazovku
- Jemný vertikální scrolling (k dispozici je 819 obrazových řádků, z nichž 240 je viditelných)
Obrázek 5: Načtení a vykreslení části obrázku do jediné bitové roviny.
Obrázek 6: Načtení a vykreslení části obrázku do dvou bitových rovin.
Obrázek 7: Načtení a vykreslení části obrázku do tří bitových rovin.
Obrázek 8: Načtení a vykreslení části obrázku do všech čtyř bitových rovin.
Obrázek 9: Začátek jemného vertikálního scrollingu.
Obrázek 10: Snímek získaný po dokončení scrollingu.
Samozřejmě není problém přidat i další funkce, například jemný horizontální scrolling či režim split-screen. Postačuje k tomu (nepatrný) přepis demonstračních příkladů uvedených minule.
11. Úplný zdrojový kód dnešního prvního demonstračního příkladu: demo využívající režim X
Úplný zdrojový kód dnešního prvního demonstračního příkladu vypadá následovně (celková velikost po překladu je 64285 bajtů, což po odečtení velikosti obrázků dává stále rozumných 285 bajtů programového kódu + tabulky CRTC registrů):
; Graficky rezim karty VGA s rozlisenim 320x240 pixelu. ; Vypnuti zretezeni bitovych rovin. ; Vykresleni rastroveho obrazku postupne do vsech bitovych rovin. ; Odskrolovani obrazku. ; ; preklad pomoci: ; nasm -f bin -o vga.com vga_320x240_image.asm ; ; nebo pouze: ; nasm -o vga.com vga_320x240_image.asm ; Nastaveni registru VGA pro rezim X ; ------------------------------------------------------ ; Register name port index 13h mode X ; Miscellaneous Output 0x3C2 N/A 0x63 0xE3 ; Memory Mode Register 0x3C4 0x04 0x0E 0x06 ; Mode Register 0x3CE 0x05 0x40 0x40 ; Miscellaneous Register 0x3CE 0x06 0x05 0x05 ; Vertical Total 0x3D4 0x06 0xBF 0x0D ; Overflow Register 0x3D4 0x07 0x1F 0x3E ; Vertical Retrace Start 0x3D4 0x10 0x9C 0xEA ; Vertical Retrace End 0x3D4 0x11 0x8E 0xAC ; Vertical Display End 0x3D4 0x12 0x8F 0xDF ; Underline Location 0x3D4 0x14 0x40 0x00 ; Vertical Blank Start 0x3D4 0x15 0x96 0xE7 ; Vertical Blank End 0x3D4 0x16 0xB9 0x06 ; Mode Control 0x3D4 0x17 0xA3 0xE3 ;----------------------------------------------------------------------------- ; registry karty VGA MISC_REGISTER equ 0x3c2 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 ; prepnuti do 320x240 mov dx, SEQUENCER_INDEX mov ax, 0x100 ; synchronni reset (bit cislo 1 je vynulovan) out dx, ax mov dx, MISC_REGISTER mov al, 0xe3 out dx, al ; hodiny 25 MHz obrazova frekvence 60 Hz (nastaveni polarity syncu) mov dx, SEQUENCER_INDEX mov ax, 0x300 ; restart sekvenceru (oba resety jsou zakazane) out dx, ax mov dx, CRTC_INDEX mov al, 0x11 ; Vertical Retrace End registr out dx, al inc dx in al, dx ; cteni hodnoty registru and al, 0x7f ; vypnout write protect bit (sedmi bit) out dx, al ; nyni lze zapisovat do jakehokoli CRTC registru mov dx, CRTC_INDEX ; budou se zapisovat hodnoty CRTC registru cld ; smer prenosu (pro jistotu) mov si, crtc_values ; tabulka s hodnotami CRTC registru mov cx, 10 ; velikost tabulky s hodnotami CRTC registru set_crtc: lodsw ; nacteni dvojice: index registru + hodnota registru out dx, ax ; zapis do zvoleneho CRTC registru loop set_crtc ; provest vsech 10 zapisu 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 wait_key ; cekani na klavesu select_bitplane 2 ; druha bitplane mov ax, 1 call move_image_part; prenest obrazek wait_key ; cekani na klavesu select_bitplane 4 ; treti bitplane mov ax, 2 call move_image_part; prenest obrazek wait_key ; cekani na klavesu select_bitplane 8 ; ctvrta bitplane mov ax, 3 call move_image_part; prenest obrazek wait_key ; cekani na klavesu mov cx, 40 ; 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, 40*80 ; adresa, kam se bude vykreslovat 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" crtc_values: dw 00d06h ; Vertical Total dw 03e07h ; Overflow Register dw 04109h ; Cell Height (teoreticky nemusime menit) dw 0ea10h ; Vertical Retrace Start dw 0ac11h ; Vertical Retrace End dw 0df12h ; Vertical Display End dw 00014h ; Underline Location dw 0e715h ; Vertical Blank Start dw 00616h ; Vertical Blank End dw 0e317h ; Mode Control
12. Modularizace programu v NASMu bez použití linkeru
Demonstrační příklad uvedený v předchozí kapitole má celkem 235 řádků. To sice není velké množství, ovšem kvůli relativně nízké úrovni abstrakce již u takového rozsahu aplikace psané v assembleru může být výhodné se zamyslet nad rozdělením celé aplikace do několika modulů. Tento koncept je v assembleru NASM do jisté míry podporován, protože je možné do jednoho zdrojového kódu vkládat jiné zdrojové kódy příkazem %include. Navíc je podporována tvorba knihoven s možností definice globálních a lokálních symbolů. Ovšem tato podpora vyžaduje použití linkeru, což může být v případě 16bitových programů v reálném režimu pro systém DOS poněkud problematické. Proto prozatím tuto možnost nevyužijeme (ani k tomu nejsme tlačeni) a zabývat se budeme pouze rozdělením celé aplikace na moduly, které se vloží do hlavního programu. S tímto konceptem souvisí problematika tvorby lokálních návěští a taktéž zabezpečení, aby se jeden modul nevkládal vícekrát, což by znamenalo, že se všechna návěští a makra „zdvojí“ atd.
13. Lokální návěští
Podívejme se na následující podprogram (subrutinu) nazvanou move_image_part. V této subrutině je realizována programová smyčka, ve které se používá návěští bitblt:
move_image_part: mov si, image ; nyni DS:SI obsahuje adresu prvniho bajtu v obrazku add si, ax ; offset pixelu mov di, 40*80 ; adresa, kam se bude vykreslovat 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
Podobných programových smyček může být ve větší aplikaci realizováno několik set nebo i několik tisíc. Problém spočívá v tom, jak pojmenovat návěští takových smyček, protože například návěští bitblt je globální a jeho použitím zde znemožníme pojmenovat návěští v jiné části aplikace stejným jménem. Jedno z řešení nabízené assemblerem NASM spočívá ve využití lokálních návěští, které začínají tečkou. Taková návěští jsou navázána na nejbližší předchozí globální návěští (představte si například triviální spojení jména tohoto návěští s návěstím lokálním) a proto můžeme návěští .bitblt (s tečkou) realizovat několikrát v různých subrutinách, a to bez jmenné kolize:
move_image_part: mov si, image ; nyni DS:SI obsahuje adresu prvniho bajtu v obrazku add si, ax ; offset pixelu mov di, 40*80 ; adresa, kam se bude vykreslovat 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
14. Zamezení vložení modulu vícekrát do hlavního programu při překladu
Pokud nějakou subrutinu, datový blok nebo makro umístíme do zvláštního souboru, můžeme tento soubor vložit do hlavního programu takto:
%include jméno_souboru.asm (nebo .inc)
Jak ovšem zajistit, aby se (omylem nebo nepřímo) soubor vkládal několikrát?:
%include jméno_souboru.asm ... ... ... %include jméno_souboru.asm
To by způsobilo jmenné kolize. V programovacím jazyku C máme stejný problém, který je typicky řešen testem existence nějakého symbolu preprocesoru. Pokud symbol již existuje, je vše v pořádku (include proběhl), pokud ne, je symbol vytvořen a použit při příštím include:
#ifndef VYBRANY_SYMBOL #define VYBRANY_SYMBOL ... ... ... #endif
V assembleru NASM lze použít naprosto stejný koncept, odlišuje se jen znak určující, že se jedná o příkazy preprocesoru:
%ifndef VYBRANY_SYMBOL %define VYBRANY_SYMBOL ... ... ... %endif
15. Modul s makry pro I/O operace
Nyní se již můžeme podívat na velmi jednoduchý modul, do kterého budeme postupně vkládat různé vstupně-výstupní operace a ovládání procesu (typicky jeho ukončení). Prozatím je tento modul velmi krátký a obsahuje pouze dvojici maker, která již dobře známe:
;----------------------------------------------------------------------------- ; Symboly, makra a subrutiny pro zjednoduseni I/O operaci ;----------------------------------------------------------------------------- %ifndef IO_LIB %define IO_LIB ;----------------------------------------------------------------------------- ; makra ;----------------------------------------------------------------------------- ; 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 %endif
16. Symboly, makra a subrutiny pro zjednodušení programování grafické karty VGA
Druhý modul je již mnohem delší. Jsou do něj uloženy symboly (datové bloky), makra a subrutiny použité pro zjednodušení programování grafické karty VGA, a to včetně nastavení režimu X. Prozatím může tento modul vypadat následovně (povšimněte si použití lokálních návěští tam, kde to má význam):
;----------------------------------------------------------------------------- ; Symboly, makra a subrutiny pro zjednoduseni programovaci graficke karty VGA ;----------------------------------------------------------------------------- %ifndef VGA_LIB ;----------------------------------------------------------------------------- ; symboly ;----------------------------------------------------------------------------- ; registry karty VGA MISC_REGISTER equ 0x3c2 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 ;----------------------------------------------------------------------------- ; makra ;----------------------------------------------------------------------------- ; 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 ; presun obrazku %macro move_one_bitplane 3 mov si, %1 ; nyni DS:SI obsahuje adresu prvniho bajtu v obrazku add si, ax ; offset pixelu mov di, %2 ; adresa, kam se bude vykreslovat mov cx, %3 ; 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 %endmacro ; nastaveni pocatecni adresy video RAM %macro set_video_ram_start 1 set_crtc_register START_ADDRESS_HIGH, %1h set_crtc_register START_ADDRESS_LOW, %1l %endmacro ;----------------------------------------------------------------------------- ; podprogramy ;----------------------------------------------------------------------------- gfx_mode_x: ; Nastaveni registru VGA pro rezim X ; ------------------------------------------------------ ; Register name port index 13h mode X ; Miscellaneous Output 0x3C2 N/A 0x63 0xE3 ; Memory Mode Register 0x3C4 0x04 0x0E 0x06 ; Mode Register 0x3CE 0x05 0x40 0x40 ; Miscellaneous Register 0x3CE 0x06 0x05 0x05 ; Vertical Total 0x3D4 0x06 0xBF 0x0D ; Overflow Register 0x3D4 0x07 0x1F 0x3E ; Vertical Retrace Start 0x3D4 0x10 0x9C 0xEA ; Vertical Retrace End 0x3D4 0x11 0x8E 0xAC ; Vertical Display End 0x3D4 0x12 0x8F 0xDF ; Underline Location 0x3D4 0x14 0x40 0x00 ; Vertical Blank Start 0x3D4 0x15 0x96 0xE7 ; Vertical Blank End 0x3D4 0x16 0xB9 0x06 ; Mode Control 0x3D4 0x17 0xA3 0xE3 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 ; prepnuti do 320x240 mov dx, SEQUENCER_INDEX mov ax, 0x100 ; synchronni reset (bit cislo 1 je vynulovan) out dx, ax mov dx, MISC_REGISTER mov al, 0xe3 out dx, al ; hodiny 25 MHz obrazova frekvence 60 Hz (nastaveni polarity syncu) mov dx, SEQUENCER_INDEX mov ax, 0x300 ; restart sekvenceru (oba resety jsou zakazane) out dx, ax mov dx, CRTC_INDEX mov al, 0x11 ; Vertical Retrace End registr out dx, al inc dx in al, dx ; cteni hodnoty registru and al, 0x7f ; vypnout write protect bit (sedmi bit) out dx, al ; nyni lze zapisovat do jakehokoli CRTC registru mov dx, CRTC_INDEX ; budou se zapisovat hodnoty CRTC registru cld ; smer prenosu (pro jistotu) mov si, crtc_values ; tabulka s hodnotami CRTC registru mov cx, 10 ; velikost tabulky s hodnotami CRTC registru .set_crtc: lodsw ; nacteni dvojice: index registru + hodnota registru out dx, ax ; zapis do zvoleneho CRTC registru loop .set_crtc ; provest vsech 10 zapisu 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 crtc_values: dw 00d06h ; Vertical Total dw 03e07h ; Overflow Register dw 04109h ; Cell Height (teoreticky nemusime menit) dw 0ea10h ; Vertical Retrace Start dw 0ac11h ; Vertical Retrace End dw 0df12h ; Vertical Display End dw 00014h ; Underline Location dw 0e715h ; Vertical Blank Start dw 00616h ; Vertical Blank End dw 0e317h ; Mode Control %endif
17. Přepis demonstračního příkladu tak, aby se využívaly moduly
Nyní si již můžeme demonstrační příklad z jedenácté kapitoly přepsat do modulární podoby. Samotný příklad bude značně zkrácen, protože množství maker a subrutin je pouze vkládáno do hlavního programu:
; Graficky rezim karty VGA s rozlisenim 320x240 pixelu. ; Vyuziti souboru se symboly, makry a podprogramy. ; Vypnuti zretezeni bitovych rovin. ; Vykresleni rastroveho obrazku postupne do vsech bitovych rovin. ; Odskrolovani obrazku. ; Pouziti knihovnich funkci. ; ; preklad pomoci: ; nasm -f bin -o vga.com vga_320x240_lib.asm ; ; nebo pouze: ; nasm -o vga.com vga_320x240_lib.asm ;----------------------------------------------------------------------------- org 0x100 ; zacatek kodu pro programy typu COM (vzdy se zacina na 256) start: jmp main ; skok na zacatek kodu %include "io.asm" ; nacist symboly, makra a podprogramy %include "vga_lib.asm" ; nacist symboly, makra a podprogramy main: call gfx_mode_x ; nastavit rezim X 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 wait_key ; cekani na klavesu select_bitplane 2 ; druha bitplane mov ax, 1 call move_image_part; prenest obrazek wait_key ; cekani na klavesu select_bitplane 4 ; treti bitplane mov ax, 2 call move_image_part; prenest obrazek wait_key ; cekani na klavesu select_bitplane 8 ; ctvrta bitplane mov ax, 3 call move_image_part; prenest obrazek wait_key ; cekani na klavesu mov cx, 40 ; 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_video_ram_start b loop opak wait_key ; cekani na klavesu exit ; navrat do DOSu move_image_part: move_one_bitplane image, 40*80, 320*200/4 ret ; pridani binarnich dat s rastrovym obrazkem image: incbin "image_320x200.bin"
18. Repositář s demonstračními příklady
Demonstrační příklady napsané v assembleru, které jsou určené pro překlad s využitím assembleru NASM, byly uloženy do Git repositáře, který je dostupný na adrese https://github.com/tisnik/8bit-fame. Jednotlivé demonstrační příklady si můžete v případě potřeby stáhnout i jednotlivě bez nutnosti klonovat celý (dnes již poměrně rozsáhlý) repositář:
# | Příklad | Stručný popis | Adresa |
---|---|---|---|
1 | hello.asm | program typu „Hello world“ naprogramovaný v assembleru pro systém DOS | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/hello.asm |
2 | hello_shorter.asm | kratší varianta výskoku z procesu zpět do DOSu | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/hello_shorter.asm |
3 | hello_wait.asm | čekání na stisk klávesy | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/hello_wait.asm |
4 | hello_macros.asm | realizace jednotlivých částí programu makrem | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/hello_macros.asm |
5 | gfx4_putpixel.asm | vykreslení pixelu v grafickém režimu 4 | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/gfx4_putpixel.asm |
6 | gfx6_putpixel.asm | vykreslení pixelu v grafickém režimu 6 | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/gfx6_putpixel.asm |
7 | gfx4_line.asm | vykreslení úsečky v grafickém režimu 4 | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/gfx4_line.asm |
8 | gfx6_line.asm | vykreslení úsečky v grafickém režimu 6 | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/gfx6_line.asm |
9 | gfx6_fill1.asm | vyplnění obrazovky v grafickém režimu, základní varianta | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/gfx6_fill1.asm |
10 | gfx6_fill2.asm | vyplnění obrazovky v grafickém režimu, varianta s instrukcí LOOP | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/gfx6_fill2.asm |
11 | gfx6_fill3.asm | vyplnění obrazovky instrukcí REP STOSB | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/gfx6_fill3.asm |
12 | gfx6_fill4.asm | vyplnění obrazovky, synchronizace vykreslování s paprskem | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/gfx6_fill4.asm |
13 | gfx4_image1.asm | vykreslení rastrového obrázku získaného z binárních dat, základní varianta | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/gfx4_image1.asm |
14 | gfx4_image2.asm | varianta vykreslení rastrového obrázku s využitím instrukce REP MOVSB | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/gfx4_image2.asm |
15 | gfx4_image3.asm | varianta vykreslení rastrového obrázku s využitím instrukce REP MOVSW | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/gfx4_image3.asm |
16 | gfx4_image4.asm | korektní vykreslení všech sudých řádků bitmapy | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/gfx4_image4.asm |
17 | gfx4_image5.asm | korektní vykreslení všech sudých i lichých řádků bitmapy | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/gfx4_image5.asm |
18 | gfx4_image6.asm | nastavení barvové palety před vykreslením obrázku | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/gfx4_image6.asm |
19 | gfx4_image7.asm | nastavení barvové palety před vykreslením obrázku, snížená intenzita barev | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/gfx4_image7.asm |
20 | gfx4_image8.asm | postupná změna barvy pozadí | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/gfx4_image8.asm |
21 | gfx6_putpixel1.asm | vykreslení pixelu, základní varianta se 16bitovým násobením | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/gfx6_putpixel1.asm |
22 | gfx6_putpixel2.asm | vykreslení pixelu, varianta s osmibitovým násobením | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/gfx6_putpixel2.asm |
23 | gfx6_putpixel3.asm | vykreslení pixelu, varianta bez násobení | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/gfx6_putpixel3.asm |
24 | gfx6_putpixel4.asm | vykreslení pixelu přes obrázek, nekorektní chování (přepis obrázku) | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/gfx6_putpixel4.asm |
25 | gfx6_putpixel5.asm | vykreslení pixelu přes obrázek, korektní varianta pro bílé pixely | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/gfx6_putpixel5.asm |
26 | cga_text_mode1.asm | standardní textový režim s rozlišením 40×25 znaků | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/cga_text_mode1.asm |
27 | cga_text_mode3.asm | standardní textový režim s rozlišením 80×25 znaků | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/cga_text_mode3.asm |
28 | cga_text_mode_intensity.asm | změna významu nejvyššího bitu atributového bajtu: vyšší intenzita namísto blikání | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/cga_text_mode_intensity.asm |
29 | cga_text_mode_cursor.asm | změna tvaru textového kurzoru | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/cga_text_mode_cursor.asm |
30 | cga_text_gfx1.asm | zobrazení „rastrové mřížky“: pseudografický režim 160×25 pixelů (interně textový režim) | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/cga_text_gfx1.asm |
31 | cga_text_mode_char_height.asm | změna výšky znaků | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/cga_text_mode_char_height.asm |
32 | cga_text_160×100.asm | grafický režim 160×100 se šestnácti barvami (interně upravený textový režim) | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/cga_text_160×100.asm |
33 | hercules_text_mode1.asm | využití standardního textového režimu společně s kartou Hercules | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/hercules_text_mode1.asm |
34 | hercules_text_mode2.asm | zákaz blikání v textových režimech | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/hercules_text_mode2.asm |
35 | hercules_turn_off.asm | vypnutí generování video signálu | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/hercules_turn_off.asm |
36 | hercules_gfx_mode1.asm | přepnutí karty Hercules do grafického režimu (základní varianta) | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/hercules_gfx_mode1.asm |
37 | hercules_gfx_mode2.asm | přepnutí karty Hercules do grafického režimu (vylepšená varianta) | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/hercules_gfx_mode2.asm |
38 | hercules_putpixel.asm | subrutina pro vykreslení jediného pixelu na kartě Hercules | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/hercules_putpixel.asm |
39 | ega_text_mode_80×25.asm | standardní textový režim 80×25 znaků na kartě EGA | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/ega_text_mode_80×25.asm |
40 | ega_text_mode_80×43.asm | zobrazení 43 textových řádků na kartě EGA | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/ega_text_mode_80×43.asm |
41 | ega_gfx_mode_320×200.asm | přepnutí do grafického režimu 320×200 pixelů se šestnácti barvami | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/ega_gfx_mode_320×200.asm |
42 | ega_gfx_mode_640×200.asm | přepnutí do grafického režimu 640×200 pixelů se šestnácti barvami | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/ega_gfx_mode_640×200.asm |
43 | ega_gfx_mode_640×350.asm | přepnutí do grafického režimu 640×350 pixelů se čtyřmi nebo šestnácti barvami | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/ega_gfx_mode_640×350.asm |
44 | ega_gfx_mode_bitplanes1.asm | ovládání zápisu do bitových rovin v planárních grafických režimech (základní způsob) | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/ega_gfx_mode_bitplanes1.asm |
45 | ega_gfx_mode_bitplanes2.asm | ovládání zápisu do bitových rovin v planárních grafických režimech (rychlejší způsob) | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/ega_gfx_mode_bitplanes2.asm |
46 | ega_320×200_putpixel.asm | vykreslení pixelu v grafickém režimu 320×200 pixelů se šestnácti barvami | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/ega_320×200_putpixel.asm |
47 | ega_640×350_putpixel.asm | vykreslení pixelu v grafickém režimu 640×350 pixelů se šestnácti barvami | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/ega_640×350_putpixel.asm |
48 | ega_standard_font.asm | použití standardního fontu grafické karty EGA | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/ega_standard_font.asm |
49 | ega_custom_font.asm | načtení vlastního fontu s jeho zobrazením | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/ega_custom_font.asm |
50 | ega_palette1.asm | změna barvové palety (všech 16 barev) v grafickém režimu 320×200 se šestnácti barvami | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/ega_palette1.asm |
51 | ega_palette2.asm | změna barvové palety (všech 16 barev) v grafickém režimu 640×350 se šestnácti barvami | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/ega_palette2.asm |
52 | ega_palette3.asm | změna všech barev v barvové paletě s využitím programové smyčky | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/ega_palette3.asm |
53 | ega_palette4.asm | změna všech barev, včetně barvy okraje, v barvové paletě voláním funkce BIOSu | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/ega_palette4.asm |
54 | vga_text_mode_80×25.asm | standardní textový režim 80×25 znaků na kartě VGA | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/vga_text_mode_80×25.asm |
55 | vga_text_mode_80×50.asm | zobrazení 50 a taktéž 28 textových řádků na kartě VGA | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/vga_text_mode_80×50.asm |
56 | vga_text_mode_intensity1.asm | změna chování atributového bitu pro blikání (nebezpečná varianta změny registrů) | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/vga_text_mode_intensity1.asm |
57 | vga_text_mode_intensity2.asm | změna chování atributového bitu pro blikání (bezpečnější varianta změny registrů) | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/vga_text_mode_intensity2.asm |
58 | vga_text_mode_9th_column.asm | modifikace způsobu zobrazení devátého sloupce ve znakových režimech (720 pixelů na řádku) | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/vga_text_mode_9th_column.asm |
59 | vga_text_mode_cursor_shape.asm | změna tvaru textového kurzoru na grafické kartě VGA | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/vga_text_mode_cursor_shape.asm |
60 | vga_text_mode_custom_font.asm | načtení vlastního fontu s jeho zobrazením | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/vga_text_mode_custom_font.asm |
61 | vga_gfx_mode_640×480.asm | přepnutí do grafického režimu 640×480 pixelů se šestnácti barvami, vykreslení vzorků | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/vga_gfx_mode_640×480.asm |
62 | vga_gfx_mode_320×200.asm | přepnutí do grafického režimu 320×200 pixelů s 256 barvami, vykreslení vzorků | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/vga_gfx_mode_320×200.asm |
63 | vga_gfx_mode_palette.asm | změna všech barev v barvové paletě grafické karty VGA | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/vga_gfx_mode_palette.asm |
64 | vga_gfx_mode_dac1.asm | využití DAC (neočekávané výsledky) | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/vga_gfx_mode_dac1.asm |
65 | vga_gfx_mode_dac2.asm | využití DAC (očekávané výsledky) | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/vga_gfx_mode_dac2.asm |
66 | vga_640×480_putpixel.asm | realizace algoritmu pro vykreslení pixelu v grafickém režimu 640×480 pixelů se šestnácti barvami | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/vga_640×480_putpixel.asm |
67 | vga_320×200_putpixel1.asm | realizace algoritmu pro vykreslení pixelu v grafickém režimu 320×200 s 256 barvami (základní varianta) | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/vga_320×200_putpixel1.asm |
68 | vga_320×200_putpixel2.asm | realizace algoritmu pro vykreslení pixelu v grafickém režimu 320×200 s 256 barvami (rychlejší varianta) | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/vga_320×200_putpixel2.asm |
69 | vga_gfx_mode_dac3.asm | přímé využití DAC v grafickém režimu 13h | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/vga_gfx_mode_dac3.asm |
70 | vga_gfx_mode_unchained_step1.asm | zobrazení barevných pruhů v režimu 13h | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/vga_gfx_mode_unchained_step1.asm |
71 | vga_gfx_mode_unchained_step2.asm | vypnutí zřetězení bitových rovin a změna způsobu adresování pixelů | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/vga_gfx_mode_unchained_step2.asm |
72 | vga_gfx_mode_unchained_step3.asm | vykreslení barevných pruhů do vybraných bitových rovin | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/vga_gfx_mode_unchained_step3.asm |
73 | vga_gfx_mode_320×400.asm | nestandardní grafický režim s rozlišením 320×400 pixelů a 256 barvami | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/vga_gfx_mode_320×400.asm |
74 | vga_320×200_image.asm | zobrazení rastrového obrázku ve standardním grafickém režimu 320×200 pixelů | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/vga_320×200_image.asm |
75 | vga_320×200_unchained_image1.asm | zobrazení rastrového obrázku v režimu s nezřetězenými rovinami (nekorektní řešení) | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/vga_320×200_unchained_image1.asm |
76 | vga_320×200_unchained_image2.asm | zobrazení rastrového obrázku v režimu s nezřetězenými rovinami (korektní řešení) | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/vga_320×200_unchained_image2.asm |
77 | vga_320×400_unchained_image.asm | zobrazení rastrového obrázku v nestandardním režimu 320×400 pixelů | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/vga_320×400_unchained_image.asm |
78 | vga_vertical_scroll1.asm | vertikální scrolling na kartě VGA v režimu s rozlišením 320×200 pixelů | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/vga_vertical_scroll1.asm |
79 | vga_vertical_scroll2.asm | vertikální scrolling na kartě VGA v režimu s rozlišením 320×400 pixelů | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/vga_vertical_scroll2.asm |
80 | vga_split_screen1.asm | režim split-screen a scrolling, nefunční varianta | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/vga_split_screen1.asm |
81 | vga_split_screen2.asm | režim split-screen a scrolling, plně funkční varianta | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/vga_split_screen2.asm |
82 | vga_horizontal_scroll1.asm | horizontální scrolling bez rozšíření počtu pixelů na virtuálním řádku | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/vga_horizontal_scroll1.asm |
83 | vga_horizontal_scroll2.asm | horizontální scrolling s rozšířením počtu pixelů na virtuálním řádku | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/vga_horizontal_scroll2.asm |
84 | vga_horizontal_scroll3.asm | jemný horizontální scrolling s rozšířením počtu pixelů na virtuálním řádku | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/vga_horizontal_scroll3.asm |
85 | vga_320×240_image.asm | nastavení grafického režimu Mode-X, načtení a vykreslení obrázku, scrolling | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/vga_320×240_image.asm |
86 | io.asm | knihovna maker pro I/O operace | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/io.asm |
87 | vga_lib.asm | knihovna maker a podprogramů pro programování karty VGA | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/vga_lib.asm |
88 | vga_320×240_lib.asm | nastavení grafického režimu Mode-X, tentokrát knihovními funkcemi | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/vga_320×240_lib.asm |
19. 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