Obsah
2. Tvary vln, které lze využít v čipech OPL2
3. Tvary vln, které lze využít v čipech OPL3
4. Interaktivní modifikace tvaru vlny u prvního operátoru
5. Úplný zdrojový kód dnešního prvního demonstračního příkladu
6. Oprava chyby: povolení režimu kompatibilního s OPL3
7. Úplný zdrojový kód dnešního druhého demonstračního příkladu
8. Vliv změny tvaru vlny na zvuk s FM syntézou
9. Úplný zdrojový kód dnešního třetího demonstračního příkladu
10. Modifikace tvaru nosné vlny i modulátoru
11. Úplný zdrojový kód dnešního čtvrtého demonstračního příkladu
12. Režim, ve kterém je jeden kanál tvořen čtyřmi operátory
13. Realizace spojení kanálů tak, aby byly k dispozici čtyři operátory
14. Způsoby vzájemného propojení čtyř operátorů (algoritmy)
15. Interaktivní přepínání AM a FM režimů u kanálu se čtyřmi operátory
16. Úplný zdrojový kód dnešního pátého demonstračního příkladu
17. Změna parametrů obálky v režimu se čtyřmi operátory
18. Příloha: skript pro vykreslení sedmi signálů generovaných oscilátory čipu OPL3
19. Repositář s demonstračními příklady
1. Programování zvukových karet s čipem OPL 3: modifikace tvaru vlny a zvukové kanály se čtyřmi operátory
Již popáté se v seriálu o tvorbě her a grafických dem na platformě IBM PC vracíme k tématu programování zvukových karet, které obsahují čipy OPL2, dvojici čipů OPL2 nebo novější čip OPL3. Základy tvorby hudby s využitím OPL2 byly popsány v článcích Zvuky a hudba na platformě IBM PC: čip OPL2 aneb Yamaha YM3812 a Zvuky a hudba na platformě IBM PC: složitější zvuky s OPL2, dalšímu vývoji zvukových karet od OPL2 směrem k OPL3 jsme se věnovali v článku Vývoj zvukových karet pro platformu IBM PC po vydání karty AdLib a minule jsme si ukázali, jakým způsobem je možné využít dvě nové vlastnosti OPL3: možnost tvorby stereo zvuku a taktéž využití osmnácti zvukových kanálů s celkem 36 operátory.
Dnes si ukážeme další možnosti OPL3. V první řadě je vhodné prozkoumat, jaké nové tvary vln (waveform) jsou dostupné a nesmíme zapomenout ještě na mnohem zásadnější změnu – na možnost spojit některé zvukové kanály takovým způsobem, aby se zde využily čtyři operátory a nikoli pouze operátory dva. To, společně s výběrem AM či FM (resp. PM) syntézy a taktéž s možností nastavení zpětné vazby značným způsobem rozšiřuje možnosti čipů OPL3 (které navíc nebyly poměrně dlouho dobře využívány), i když v oblasti profesionální hudby se používá ještě větší počet operátorů. Například slavné klávesy Yamaha DX7 nabízely šest operátorů a celkem 32 jejich kombinací (zde nazývaných „algoritmy“). K tomu se ovšem ještě vrátíme později v článcích o MIDI.
2. Tvary vln, které lze využít v čipech OPL2
Nejprve se na chvíli vraťme k čipům OPL2, které jsou interně jednodušší a tím pádem i snadnější na pochopení. V těchto čipech mohl každý oscilátor (v OPL2 jich bylo celkem osmnáct) generovat periodický signál odvozený od klasické sinusovky. Podoba této sinusovky je uložena v ROM přímo na hudebním čipu. Přesněji řečeno je zde uložena jen jedna čtvrtina sinusovky, protože zbylé části lze snadno dopočítat zrcadlením okolo x-ové nebo y-ové osy (navíc jsou hodnoty uloženy zlogaritmované, aby se snadněji násobily, to je však interní vlastnost OPL2, s níž se přímo nesetkáme). Všechny čtyři varianty signálu podporované OPL2 jsou zobrazeny na dalším obrázku:
Obrázek 1: Sinusová vlna.
Obrázek 2: Jen kladné půlvlny.
Tvary vlny bylo možné volit nastavením spodních dvou bitů registrů E0 až F5 (tedy skutečně pro každý operátor – nikoli pouze pro kanál).
Obrázek 3: Absolutní hodnota sinusovky.
Obrázek 4: Jen náběžné hrany sinusovky.
3. Tvary vln, které lze využít v čipech OPL3
V čipech OPL3 se k původním čtyřem volitelným tvarům vln přidaly ještě další čtyři tvary. Jedná se v první řadě o sinusovku upravenou takovým způsobem, že nenulové jsou jen vlny ze sudých period a dále o absolutní hodnoty tohoto průběhu:
Obrázek 5: Pouze sudé periody sinusovky.
Obrázek 6: Absolutní hodnota předešlého signálu.
Další dva tvary vln jsou zcela odlišné, protože se jedná o obdélníkový signál (tak oblíbený ve starších čipech z éry osmibitových domácích mikropočítačů a herních konzolí) a taktéž o signál, který zhruba odpovídá derivaci obdélníkového signálu – záporný impuls následovaný kladným impulsem (na rozdíl od skutečné derivace samozřejmě nejde o Diracovy impulsy).
<Obrázek 7: Obdélníkový průběh.
Samotný signál s derivací obdélníkového signálu ve skutečnosti vypadá následovně.
Tvary vln, tedy opět výběr jednoho z osmi dostupných tvarů, se stále provádí přes registry E0 až F5, kde nyní mají význam spodní tři bity a nejenom bity dva.
4. Interaktivní modifikace tvaru vlny u prvního operátoru
Vyzkoušejme si, jakým způsobem je možné modifikovat tvar vlny generované oscilátorem, jenž je připojený na první operátor prvního kanálu. Nejprve nastavíme AM syntézu, takže se výsledný signál produkovaný prvním operátorem přímo pošle na D/A převodník a nebude se jednat o „pouhý“ modulátor pro FM syntézu. Do tabulky s nastavením OPL2/OPL3 tedy zapíšeme tento řádek:
db CHANNEL_1 + OPL_FEEDBACK, 0b00110001 ; volba AM-FM
Dále nastavíme obálku pro operátor:
db CHANNEL_1_OPERATOR_1 + OPL_AMP_VIBRATO_EG, 0x01 ; nastaveni modulatoru: nasobeni frekvence jednickou db CHANNEL_1_OPERATOR_1 + OPL_LEVEL, 0x00 ; uroven vystupu 40 dB db CHANNEL_1_OPERATOR_1 + OPL_ATTACK_DECAY, 0xf0 ; modulator: pomaly nastup zvuku + pomale doznivani db CHANNEL_1_OPERATOR_1 + OPL_SUSTAIN_RELEASE, 0x77 ; urovne sustain a release pro modulator
Zvolíme základní tvar vlny:
db CHANNEL_1_OPERATOR_1 + OPL_WAVE_SELECT, 0x00 ; standardni sinus
A nastavíme frekvenci pro celý kanál:
db CHANNEL_1 + OPL_FREQUENCY_LOW, 0x41 ; frekvence zvuku (komorni A = 440 Hz) db CHANNEL_1 + OPL_KEY_ON, 0x12 ; zapnuti/povoleni zvuku + nastaveni oktavy a vyssich bitu frekvence
Samotné přepínání tvaru vlny bude provedeno klávesami 1–8 (1 je sinus, 7 je obdélník atd.) a mezerníkem se tón přehraje – nastaví se bit KEY ON tak, jak to již dobře známe:
.opak: in al, PPI_PORT_A ; cteni stisknute klavesy cmp al, KEY_SPACE ; test na stisk mezerniku jne .next_test_1 ; neni stisknut -> preskok write_opl_register CHANNEL_1 + OPL_KEY_ON, 0x32 ; povoleni KEY ON bitu jmp .opak .next_test_1: cmp al, KEY_SPACE + KEY_RELEASE ; test na pusteni mezerniku jne .next_test_2 ; neni pusten -> dalsi test write_opl_register CHANNEL_1 + OPL_KEY_ON, 0x12 ; zakaz KEY ON bitu jmp .opak .next_test_2: cmp al, KEY_1 ; test na numericke klavesy jb .next_test_3 ; hodnota "pod" kodem klavesy 1 cmp al, KEY_8 ja .next_test_3 ; hodnota "nad" kodem klavesy 8 mov bl, al ; makro prepisuje AL -> nemuzeme ho primo pouzit sub bl, KEY_1 write_opl_register CHANNEL_1_OPERATOR_1 + OPL_WAVE_SELECT, bl jmp .opak .next_test_3:
5. Úplný zdrojový kód dnešního prvního demonstračního příkladu
Úplný zdrojový kód demonstračního příkladu umožňujícího interaktivní změnu tvaru vlny pomocí kláves 1–8 vypadá následovně:
; Prehrani zakladniho tonu na kartach s cipem OPL3. ; Prepinani tvaru vlny pro generovani zvuku. ; Pojmenovani registru OPL3. ; Ovladani KEY ON mezernikem ; Tvar vlny je rizen klavesami 1 az 8 ; Ukonceni aplikace stiskem ESC ; ; ; Tento demonstracni priklad je pouzity v serialu o programovani ; grafickych dem a her na PC v DOSu: ; https://www.root.cz/serialy/vyvoj-her-a-grafickych-dem-pro-platformu-pc/ ; ; ; preklad pomoci: ; nasm -f bin -o sounds_opl3_waveform_1.com sounds_opl3_waveform_1.asm ; ; nebo pouze: ; nasm -o sounds_opl3_waveform_1.com sounds_opl3_waveform_1.asm ;----------------------------------------------------------------------------- BITS 16 ; 16bitovy vystup pro DOS CPU 8086 ; specifikace pouziteho instrukcniho souboru ;----------------------------------------------------------------------------- ; registry karet s cipem OPL2 nebo OPL3 OPL_ADDRESS equ 0x220 OPL_DATA equ 0x221 ; ridici registry OPL2 OPL_TEST_LSI equ 0x01 OPL_TIMER_1 equ 0x02 OPL_TIMER_2 equ 0x03 OPL_TIMER_CTRL equ 0x04 OPL_KBSPLIT equ 0x08 OPL_AMP_VIBRATO_EG equ 0x20 OPL_LEVEL equ 0x40 OPL_ATTACK_DECAY equ 0x60 OPL_SUSTAIN_RELEASE equ 0x80 OPL_FREQUENCY_LOW equ 0xa0 OPL_KEY_ON equ 0xb0 OPL_AM_VIBRATO_RHYTHM equ 0xbd OPL_FEEDBACK equ 0xc0 OPL_WAVE_SELECT equ 0xe0 OPL3_MODE_ENABLE equ 0x05 ; vyssi port!!! ; indexy kanalu CHANNEL_1 equ 0 CHANNEL_2 equ 1 CHANNEL_3 equ 2 CHANNEL_4 equ 3 CHANNEL_5 equ 4 CHANNEL_6 equ 5 CHANNEL_7 equ 6 CHANNEL_8 equ 7 CHANNEL_9 equ 8 ; offsety pro jednotlive operatory ; -------------------------------------------------- ; Channel 1 2 3 4 5 6 7 8 9 ; Operator 1 00 01 02 08 09 0A 10 11 12 ; Operator 2 03 04 05 0B 0C 0D 13 14 15 ; -------------------------------------------------- ; Channel 1 2 3 4 5 6 7 8 9 CHANNEL_1_OPERATOR_1 equ 0x00 CHANNEL_1_OPERATOR_2 equ 0x03 CHANNEL_2_OPERATOR_1 equ 0x01 CHANNEL_2_OPERATOR_2 equ 0x04 CHANNEL_3_OPERATOR_1 equ 0x02 CHANNEL_3_OPERATOR_2 equ 0x05 CHANNEL_4_OPERATOR_1 equ 0x08 CHANNEL_4_OPERATOR_2 equ 0x0b CHANNEL_5_OPERATOR_1 equ 0x09 CHANNEL_5_OPERATOR_2 equ 0x0c CHANNEL_6_OPERATOR_1 equ 0x0a CHANNEL_6_OPERATOR_2 equ 0x0d CHANNEL_7_OPERATOR_1 equ 0x10 CHANNEL_7_OPERATOR_2 equ 0x13 CHANNEL_8_OPERATOR_1 equ 0x11 CHANNEL_8_OPERATOR_2 equ 0x14 CHANNEL_9_OPERATOR_1 equ 0x12 CHANNEL_9_OPERATOR_2 equ 0x15 ; registry PPI PPI_PORT_A equ 0x60 PPI_PORT_B equ 0x61 ; kody klaves KEY_ESC equ 0x01 KEY_SPACE equ 0x39 KEY_RELEASE equ 0x80 KEY_1 equ 0x02 KEY_8 equ KEY_1 + 8 ;----------------------------------------------------------------------------- ; ukonceni procesu a navrat do DOSu %macro exit 0 ret %endmacro ; makro pro zapis do registru OPL2 %macro write_opl_register 2 mov al, %1 mov ah, %2 call perform_write_to_opl_register %endmacro ;----------------------------------------------------------------------------- org 0x100 ; zacatek kodu pro programy typu COM (vzdy se zacina na 256) start: push cs pop ds ; DS==CS mov si, tone1 ; zacatek tabulky call write_table_to_opl2 ; zapis obsahu tabulky do OPL2 in al, PPI_PORT_B ; port B s rizenim zarizeni or al, 0b1000000 ; nastaveni bitu cislo 7 na jednicku out PPI_PORT_B, al ; zapis zpet na port B .opak: in al, PPI_PORT_A ; cteni stisknute klavesy cmp al, KEY_SPACE ; test na stisk mezerniku jne .next_test_1 ; neni stisknut -> preskok write_opl_register CHANNEL_1 + OPL_KEY_ON, 0x32 ; povoleni KEY ON bitu jmp .opak .next_test_1: cmp al, KEY_SPACE + KEY_RELEASE ; test na pusteni mezerniku jne .next_test_2 ; neni pusten -> dalsi test write_opl_register CHANNEL_1 + OPL_KEY_ON, 0x12 ; zakaz KEY ON bitu jmp .opak .next_test_2: cmp al, KEY_1 ; test na numericke klavesy jb .next_test_3 ; hodnota "pod" kodem klavesy 1 cmp al, KEY_8 ja .next_test_3 ; hodnota "nad" kodem klavesy 8 mov bl, al ; makro prepisuje AL -> nemuzeme ho primo pouzit sub bl, KEY_1 write_opl_register CHANNEL_1_OPERATOR_1 + OPL_WAVE_SELECT, bl jmp .opak .next_test_3: cmp al, KEY_ESC ; test stisknute klavesy ESC jne .opak ; neni stisknuta? -> zkusme znovu exit write_table_to_opl2: lodsb ; nacist bajt z tabulky (cislo registru) or al, al ; test na nulu jnz .write_register ret ; dosahli jsme konce tabulky .write_register: mov ah, al lodsb ; nacist dalsi bajt z tabulky (hodnota registru) xchg al, ah ; podprogram vyzaduje opacne poradi AL, AH call perform_write_to_opl_register jmp write_table_to_opl2 ; muzeme prejit na dalsi registr tone1: ; tabulka s tonem pro prvni kanal db CHANNEL_1_OPERATOR_1 + OPL_AMP_VIBRATO_EG, 0x01 ; nastaveni modulatoru: nasobeni frekvence jednickou db CHANNEL_1_OPERATOR_1 + OPL_LEVEL, 0x00 ; uroven vystupu 40 dB db CHANNEL_1_OPERATOR_1 + OPL_ATTACK_DECAY, 0xf0 ; modulator: pomaly nastup zvuku + pomale doznivani db CHANNEL_1_OPERATOR_1 + OPL_SUSTAIN_RELEASE, 0x77 ; urovne sustain a release pro modulator db CHANNEL_1_OPERATOR_2 + OPL_AMP_VIBRATO_EG, 0x01 ; nastaveni nosne: nasobeni frekvence jednickou db CHANNEL_1_OPERATOR_2 + OPL_LEVEL, 0x00 ; nastaveni urovne vystupu nosne na 47 dB db CHANNEL_1_OPERATOR_2 + OPL_ATTACK_DECAY, 0xf0 ; nosna: rychly nastup + pomale doznivani db CHANNEL_1_OPERATOR_2 + OPL_SUSTAIN_RELEASE, 0x77 ; urovne sustain a release pro nosnou db CHANNEL_1_OPERATOR_1 + OPL_WAVE_SELECT, 0x00 ; standardni sinus db CHANNEL_1 + OPL_FREQUENCY_LOW, 0x41 ; frekvence zvuku (komorni A = 440 Hz) db CHANNEL_1 + OPL_KEY_ON, 0x12 ; zapnuti/povoleni zvuku + nastaveni oktavy a vyssich bitu frekvence db CHANNEL_1 + OPL_FEEDBACK, 0b00110001 ; volba AM-FM db 0, 0 ; zarazka perform_write_to_opl_register: ; zapis do vybraneho registru OPL2 ; AL - registr ; AH - hodnota mov dx, OPL_ADDRESS ; vyber registru pro modifikaci out dx, al mov al, ah ; zapis hodnoty do vybraneho registru mov dx, OPL_DATA out dx, al ret
6. Oprava chyby: povolení režimu kompatibilního s OPL3
V případě, že jste si předchozí demonstrační příklad skutečně přeložili a vyzkoušeli, pravděpodobně jste zjistili, že tóny po stisku kláves 1 a 5 jsou totožné. Totéž platí pro klávesy 2 a 6 atd. Je tomu tak z toho důvodu, že po resetu je čip OPL3 nastaven do režimu zpětné kompatibility s čipem OPL2, což omezuje jak nastavení sterea (což jsme viděli minule), tak i možnost využití třetího bitu v registrech E0 až F5 – význam tudíž mají jen nejnižší dva bity. Aby bylo možné vybrat i další čtyři tvary vln, je nutné se přepnout do režimu kompatibilního s OPL3:
write_opl_high_register OPL3_MODE_ENABLE, 1
Pro tento účel slouží následující makro:
; makro pro zapis do "vyssiho" registru OPL3 %macro write_opl_high_register 2 mov al, %1 mov ah, %2 call perform_write_to_opl_high_register %endmacro
To využívá subrutinu pro zápis do vybraného vyššího registru OPL3:
perform_write_to_opl_high_register: ; zapis do vybraneho "vyssiho" registru OPL3 ; AL - registr ; AH - hodnota mov dx, OPL_HIGH_ADDRESS ; vyber registru pro modifikaci out dx, al mov al, ah ; zapis hodnoty do vybraneho registru mov dx, OPL_HIGH_DATA out dx, al ret
7. Úplný zdrojový kód dnešního druhého demonstračního příkladu
Opravená varianta demonstračního příkladu, který nyní umožní skutečně vybrat jednu z osmi dostupných tvarů vln, vypadá následovně:
; Prehrani zakladniho tonu na kartach s cipem OPL3. ; Prepnuti do rezimu OPL3. ; Prepinani tvaru vlny pro generovani zvuku. ; Pojmenovani registru OPL3. ; Ovladani KEY ON mezernikem ; Tvar vlny je rizen klavesami 1 az 8 ; Ukonceni aplikace stiskem ESC ; ; ; Tento demonstracni priklad je pouzity v serialu o programovani ; grafickych dem a her na PC v DOSu: ; https://www.root.cz/serialy/vyvoj-her-a-grafickych-dem-pro-platformu-pc/ ; ; ; preklad pomoci: ; nasm -f bin -o sounds_opl3_waveform_2.com sounds_opl3_waveform_2.asm ; ; nebo pouze: ; nasm -o sounds_opl3_waveform_2.com sounds_opl3_waveform_2.asm ;----------------------------------------------------------------------------- BITS 16 ; 16bitovy vystup pro DOS CPU 8086 ; specifikace pouziteho instrukcniho souboru ;----------------------------------------------------------------------------- ; registry karet s cipem OPL3 OPL_ADDRESS equ 0x220 OPL_DATA equ 0x221 OPL_HIGH_ADDRESS equ 0x222 OPL_HIGH_DATA equ 0x223 ; ridici registry OPL2 OPL_TEST_LSI equ 0x01 OPL_TIMER_1 equ 0x02 OPL_TIMER_2 equ 0x03 OPL_TIMER_CTRL equ 0x04 OPL_KBSPLIT equ 0x08 OPL_AMP_VIBRATO_EG equ 0x20 OPL_LEVEL equ 0x40 OPL_ATTACK_DECAY equ 0x60 OPL_SUSTAIN_RELEASE equ 0x80 OPL_FREQUENCY_LOW equ 0xa0 OPL_KEY_ON equ 0xb0 OPL_AM_VIBRATO_RHYTHM equ 0xbd OPL_FEEDBACK equ 0xc0 OPL_WAVE_SELECT equ 0xe0 OPL3_MODE_ENABLE equ 0x05 ; vyssi port!!! ; indexy kanalu CHANNEL_1 equ 0 CHANNEL_2 equ 1 CHANNEL_3 equ 2 CHANNEL_4 equ 3 CHANNEL_5 equ 4 CHANNEL_6 equ 5 CHANNEL_7 equ 6 CHANNEL_8 equ 7 CHANNEL_9 equ 8 ; offsety pro jednotlive operatory ; -------------------------------------------------- ; Channel 1 2 3 4 5 6 7 8 9 ; Operator 1 00 01 02 08 09 0A 10 11 12 ; Operator 2 03 04 05 0B 0C 0D 13 14 15 ; -------------------------------------------------- ; Channel 1 2 3 4 5 6 7 8 9 CHANNEL_1_OPERATOR_1 equ 0x00 CHANNEL_1_OPERATOR_2 equ 0x03 CHANNEL_2_OPERATOR_1 equ 0x01 CHANNEL_2_OPERATOR_2 equ 0x04 CHANNEL_3_OPERATOR_1 equ 0x02 CHANNEL_3_OPERATOR_2 equ 0x05 CHANNEL_4_OPERATOR_1 equ 0x08 CHANNEL_4_OPERATOR_2 equ 0x0b CHANNEL_5_OPERATOR_1 equ 0x09 CHANNEL_5_OPERATOR_2 equ 0x0c CHANNEL_6_OPERATOR_1 equ 0x0a CHANNEL_6_OPERATOR_2 equ 0x0d CHANNEL_7_OPERATOR_1 equ 0x10 CHANNEL_7_OPERATOR_2 equ 0x13 CHANNEL_8_OPERATOR_1 equ 0x11 CHANNEL_8_OPERATOR_2 equ 0x14 CHANNEL_9_OPERATOR_1 equ 0x12 CHANNEL_9_OPERATOR_2 equ 0x15 ; registry PPI PPI_PORT_A equ 0x60 PPI_PORT_B equ 0x61 ; kody klaves KEY_ESC equ 0x01 KEY_SPACE equ 0x39 KEY_RELEASE equ 0x80 KEY_1 equ 0x02 KEY_8 equ KEY_1 + 8 ;----------------------------------------------------------------------------- ; ukonceni procesu a navrat do DOSu %macro exit 0 ret %endmacro ; makro pro zapis do registru OPL2 nebo OPL3 %macro write_opl_register 2 mov al, %1 mov ah, %2 call perform_write_to_opl_register %endmacro ; makro pro zapis do "vyssiho" registru OPL3 %macro write_opl_high_register 2 mov al, %1 mov ah, %2 call perform_write_to_opl_high_register %endmacro ;----------------------------------------------------------------------------- org 0x100 ; zacatek kodu pro programy typu COM (vzdy se zacina na 256) start: push cs pop ds ; DS==CS write_opl_high_register OPL3_MODE_ENABLE, 1 mov si, tone1 ; zacatek tabulky call write_table_to_opl3 ; zapis obsahu tabulky do OPL3 in al, PPI_PORT_B ; port B s rizenim zarizeni or al, 0b1000000 ; nastaveni bitu cislo 7 na jednicku out PPI_PORT_B, al ; zapis zpet na port B .opak: in al, PPI_PORT_A ; cteni stisknute klavesy cmp al, KEY_SPACE ; test na stisk mezerniku jne .next_test_1 ; neni stisknut -> preskok write_opl_register CHANNEL_1 + OPL_KEY_ON, 0x32 ; povoleni KEY ON bitu jmp .opak .next_test_1: cmp al, KEY_SPACE + KEY_RELEASE ; test na pusteni mezerniku jne .next_test_2 ; neni pusten -> dalsi test write_opl_register CHANNEL_1 + OPL_KEY_ON, 0x12 ; zakaz KEY ON bitu jmp .opak .next_test_2: cmp al, KEY_1 ; test na numericke klavesy jb .next_test_3 ; hodnota "pod" kodem klavesy 1 cmp al, KEY_8 ja .next_test_3 ; hodnota "nad" kodem klavesy 8 mov bl, al ; makro prepisuje AL -> nemuzeme ho primo pouzit sub bl, KEY_1 write_opl_register CHANNEL_1_OPERATOR_1 + OPL_WAVE_SELECT, bl jmp .opak .next_test_3: cmp al, KEY_ESC ; test stisknute klavesy ESC jne .opak ; neni stisknuta? -> zkusme znovu exit write_table_to_opl3: lodsb ; nacist bajt z tabulky (cislo registru) or al, al ; test na nulu jnz .write_register ret ; dosahli jsme konce tabulky .write_register: mov ah, al lodsb ; nacist dalsi bajt z tabulky (hodnota registru) xchg al, ah ; podprogram vyzaduje opacne poradi AL, AH call perform_write_to_opl_register jmp write_table_to_opl3 ; muzeme prejit na dalsi registr tone1: ; tabulka s tonem pro prvni kanal db CHANNEL_1_OPERATOR_1 + OPL_AMP_VIBRATO_EG, 0x01 ; nastaveni modulatoru: nasobeni frekvence jednickou db CHANNEL_1_OPERATOR_1 + OPL_LEVEL, 0x00 ; uroven vystupu 40 dB db CHANNEL_1_OPERATOR_1 + OPL_ATTACK_DECAY, 0xf0 ; modulator: pomaly nastup zvuku + pomale doznivani db CHANNEL_1_OPERATOR_1 + OPL_SUSTAIN_RELEASE, 0x77 ; urovne sustain a release pro modulator db CHANNEL_1_OPERATOR_2 + OPL_AMP_VIBRATO_EG, 0x01 ; nastaveni nosne: nasobeni frekvence jednickou db CHANNEL_1_OPERATOR_2 + OPL_LEVEL, 0x00 ; nastaveni urovne vystupu nosne na 47 dB db CHANNEL_1_OPERATOR_2 + OPL_ATTACK_DECAY, 0xf0 ; nosna: rychly nastup + pomale doznivani db CHANNEL_1_OPERATOR_2 + OPL_SUSTAIN_RELEASE, 0x77 ; urovne sustain a release pro nosnou db CHANNEL_1_OPERATOR_1 + OPL_WAVE_SELECT, 0x00 ; standardni sinus db CHANNEL_1 + OPL_FREQUENCY_LOW, 0x41 ; frekvence zvuku (komorni A = 440 Hz) db CHANNEL_1 + OPL_KEY_ON, 0x12 ; zapnuti/povoleni zvuku + nastaveni oktavy a vyssich bitu frekvence db CHANNEL_1 + OPL_FEEDBACK, 0b00110001 ; volba AM-FM db 0, 0 ; zarazka perform_write_to_opl_register: ; zapis do vybraneho registru OPL2 nebo OPL3 ; AL - registr ; AH - hodnota mov dx, OPL_ADDRESS ; vyber registru pro modifikaci out dx, al mov al, ah ; zapis hodnoty do vybraneho registru mov dx, OPL_DATA out dx, al ret perform_write_to_opl_high_register: ; zapis do vybraneho "vyssiho" registru OPL3 ; AL - registr ; AH - hodnota mov dx, OPL_HIGH_ADDRESS ; vyber registru pro modifikaci out dx, al mov al, ah ; zapis hodnoty do vybraneho registru mov dx, OPL_HIGH_DATA out dx, al ret
8. Vliv změny tvaru vlny na zvuk s FM syntézou
Oba demonstrační příklady, které jsme si doposud ukázali, měly první kanál přepnutý do režimu AM syntézy, takže se výstupy z jednotlivých operátorů přímo posílaly na D/A převodník. Ovšem tvar vlny má vliv i na tvorbu tónu s využitím FM syntézy. Můžeme si to ostatně snadno otestovat, protože FM režim je nastavený implicitně při (resp. po) resetu OPL3. Aby byl vliv FM ještě více patrný, pozměníme obálku (ADSR) obou operátorů tvořících první kanál. Tabulka s nastavením čipu OPL3 (konkrétně celého prvního kanálu) se pozmění následovně:
db CHANNEL_1_OPERATOR_1 + OPL_AMP_VIBRATO_EG, 0x01 ; nastaveni modulatoru: nasobeni frekvence jednickou db CHANNEL_1_OPERATOR_1 + OPL_LEVEL, 0x00 ; uroven vystupu 40 dB db CHANNEL_1_OPERATOR_1 + OPL_ATTACK_DECAY, 0x41 ; modulator: pomaly nastup zvuku + pomale doznivani db CHANNEL_1_OPERATOR_1 + OPL_SUSTAIN_RELEASE, 0x7f ; urovne sustain a release pro modulator db CHANNEL_1_OPERATOR_2 + OPL_AMP_VIBRATO_EG, 0x01 ; nastaveni nosne: nasobeni frekvence jednickou db CHANNEL_1_OPERATOR_2 + OPL_LEVEL, 0x00 ; nastaveni urovne vystupu nosne na 47 dB db CHANNEL_1_OPERATOR_2 + OPL_ATTACK_DECAY, 0xa2 ; nosna: rychly nastup + pomale doznivani db CHANNEL_1_OPERATOR_2 + OPL_SUSTAIN_RELEASE, 0x77 ; urovne sustain a release pro nosnou db CHANNEL_1_OPERATOR_1 + OPL_WAVE_SELECT, 0x00 ; standardni sinus db CHANNEL_1 + OPL_FREQUENCY_LOW, 0x41 ; frekvence zvuku (komorni A = 440 Hz) db CHANNEL_1 + OPL_KEY_ON, 0x12 ; zapnuti/povoleni zvuku + nastaveni oktavy a vyssich bitu frekvence db 0, 0 ; zarazka
9. Úplný zdrojový kód dnešního třetího demonstračního příkladu
Dnešní třetí demonstrační příklad, který je odvozen od příkladu druhého (pouze se změnily hodnoty některých registrů s tvary obálky atd.), vypadá následovně:
; Prehrani zakladniho tonu na kartach s cipem OPL3. ; Prepnuti do rezimu OPL3. ; Prepinani tvaru vlny pro generovani zvuku. ; Pojmenovani registru OPL3. ; Vetsi zpetna vazba (feedback). ; Ovladani KEY ON mezernikem ; Tvar vlny je rizen klavesami 1 az 8 ; Ukonceni aplikace stiskem ESC ; ; ; Tento demonstracni priklad je pouzity v serialu o programovani ; grafickych dem a her na PC v DOSu: ; https://www.root.cz/serialy/vyvoj-her-a-grafickych-dem-pro-platformu-pc/ ; ; ; preklad pomoci: ; nasm -f bin -o sounds_opl3_waveform_3.com sounds_opl3_waveform_3.asm ; ; nebo pouze: ; nasm -o sounds_opl3_waveform_3.com sounds_opl3_waveform_3.asm ;----------------------------------------------------------------------------- BITS 16 ; 16bitovy vystup pro DOS CPU 8086 ; specifikace pouziteho instrukcniho souboru ;----------------------------------------------------------------------------- ; registry karet s cipem OPL3 OPL_ADDRESS equ 0x220 OPL_DATA equ 0x221 OPL_HIGH_ADDRESS equ 0x222 OPL_HIGH_DATA equ 0x223 ; ridici registry OPL2 OPL_TEST_LSI equ 0x01 OPL_TIMER_1 equ 0x02 OPL_TIMER_2 equ 0x03 OPL_TIMER_CTRL equ 0x04 OPL_KBSPLIT equ 0x08 OPL_AMP_VIBRATO_EG equ 0x20 OPL_LEVEL equ 0x40 OPL_ATTACK_DECAY equ 0x60 OPL_SUSTAIN_RELEASE equ 0x80 OPL_FREQUENCY_LOW equ 0xa0 OPL_KEY_ON equ 0xb0 OPL_AM_VIBRATO_RHYTHM equ 0xbd OPL_FEEDBACK equ 0xc0 OPL_WAVE_SELECT equ 0xe0 OPL3_MODE_ENABLE equ 0x05 ; vyssi port!!! ; indexy kanalu CHANNEL_1 equ 0 CHANNEL_2 equ 1 CHANNEL_3 equ 2 CHANNEL_4 equ 3 CHANNEL_5 equ 4 CHANNEL_6 equ 5 CHANNEL_7 equ 6 CHANNEL_8 equ 7 CHANNEL_9 equ 8 ; offsety pro jednotlive operatory ; -------------------------------------------------- ; Channel 1 2 3 4 5 6 7 8 9 ; Operator 1 00 01 02 08 09 0A 10 11 12 ; Operator 2 03 04 05 0B 0C 0D 13 14 15 ; -------------------------------------------------- ; Channel 1 2 3 4 5 6 7 8 9 CHANNEL_1_OPERATOR_1 equ 0x00 CHANNEL_1_OPERATOR_2 equ 0x03 CHANNEL_2_OPERATOR_1 equ 0x01 CHANNEL_2_OPERATOR_2 equ 0x04 CHANNEL_3_OPERATOR_1 equ 0x02 CHANNEL_3_OPERATOR_2 equ 0x05 CHANNEL_4_OPERATOR_1 equ 0x08 CHANNEL_4_OPERATOR_2 equ 0x0b CHANNEL_5_OPERATOR_1 equ 0x09 CHANNEL_5_OPERATOR_2 equ 0x0c CHANNEL_6_OPERATOR_1 equ 0x0a CHANNEL_6_OPERATOR_2 equ 0x0d CHANNEL_7_OPERATOR_1 equ 0x10 CHANNEL_7_OPERATOR_2 equ 0x13 CHANNEL_8_OPERATOR_1 equ 0x11 CHANNEL_8_OPERATOR_2 equ 0x14 CHANNEL_9_OPERATOR_1 equ 0x12 CHANNEL_9_OPERATOR_2 equ 0x15 ; registry PPI PPI_PORT_A equ 0x60 PPI_PORT_B equ 0x61 ; kody klaves KEY_ESC equ 0x01 KEY_SPACE equ 0x39 KEY_RELEASE equ 0x80 KEY_1 equ 0x02 KEY_8 equ KEY_1 + 8 ;----------------------------------------------------------------------------- ; ukonceni procesu a navrat do DOSu %macro exit 0 ret %endmacro ; makro pro zapis do registru OPL2 nebo OPL3 %macro write_opl_register 2 mov al, %1 mov ah, %2 call perform_write_to_opl_register %endmacro ; makro pro zapis do "vyssiho" registru OPL3 %macro write_opl_high_register 2 mov al, %1 mov ah, %2 call perform_write_to_opl_high_register %endmacro ;----------------------------------------------------------------------------- org 0x100 ; zacatek kodu pro programy typu COM (vzdy se zacina na 256) start: push cs pop ds ; DS==CS write_opl_high_register OPL3_MODE_ENABLE, 1 mov si, tone1 ; zacatek tabulky call write_table_to_opl3 ; zapis obsahu tabulky do OPL3 in al, PPI_PORT_B ; port B s rizenim zarizeni or al, 0b1000000 ; nastaveni bitu cislo 7 na jednicku out PPI_PORT_B, al ; zapis zpet na port B .opak: in al, PPI_PORT_A ; cteni stisknute klavesy cmp al, KEY_SPACE ; test na stisk mezerniku jne .next_test_1 ; neni stisknut -> preskok write_opl_register CHANNEL_1 + OPL_KEY_ON, 0x32 ; povoleni KEY ON bitu jmp .opak .next_test_1: cmp al, KEY_SPACE + KEY_RELEASE ; test na pusteni mezerniku jne .next_test_2 ; neni pusten -> dalsi test write_opl_register CHANNEL_1 + OPL_KEY_ON, 0x12 ; zakaz KEY ON bitu jmp .opak .next_test_2: cmp al, KEY_1 ; test na numericke klavesy jb .next_test_3 ; hodnota "pod" kodem klavesy 1 cmp al, KEY_8 ja .next_test_3 ; hodnota "nad" kodem klavesy 8 mov bl, al ; makro prepisuje AL -> nemuzeme ho primo pouzit sub bl, KEY_1 write_opl_register CHANNEL_1_OPERATOR_1 + OPL_WAVE_SELECT, bl jmp .opak .next_test_3: cmp al, KEY_ESC ; test stisknute klavesy ESC jne .opak ; neni stisknuta? -> zkusme znovu exit write_table_to_opl3: lodsb ; nacist bajt z tabulky (cislo registru) or al, al ; test na nulu jnz .write_register ret ; dosahli jsme konce tabulky .write_register: mov ah, al lodsb ; nacist dalsi bajt z tabulky (hodnota registru) xchg al, ah ; podprogram vyzaduje opacne poradi AL, AH call perform_write_to_opl_register jmp write_table_to_opl3 ; muzeme prejit na dalsi registr tone1: ; tabulka s tonem pro prvni kanal db CHANNEL_1_OPERATOR_1 + OPL_AMP_VIBRATO_EG, 0x01 ; nastaveni modulatoru: nasobeni frekvence jednickou db CHANNEL_1_OPERATOR_1 + OPL_LEVEL, 0x00 ; uroven vystupu 40 dB db CHANNEL_1_OPERATOR_1 + OPL_ATTACK_DECAY, 0x41 ; modulator: pomaly nastup zvuku + pomale doznivani db CHANNEL_1_OPERATOR_1 + OPL_SUSTAIN_RELEASE, 0x7f ; urovne sustain a release pro modulator db CHANNEL_1_OPERATOR_2 + OPL_AMP_VIBRATO_EG, 0x01 ; nastaveni nosne: nasobeni frekvence jednickou db CHANNEL_1_OPERATOR_2 + OPL_LEVEL, 0x00 ; nastaveni urovne vystupu nosne na 47 dB db CHANNEL_1_OPERATOR_2 + OPL_ATTACK_DECAY, 0xa2 ; nosna: rychly nastup + pomale doznivani db CHANNEL_1_OPERATOR_2 + OPL_SUSTAIN_RELEASE, 0x77 ; urovne sustain a release pro nosnou db CHANNEL_1_OPERATOR_1 + OPL_WAVE_SELECT, 0x00 ; standardni sinus db CHANNEL_1 + OPL_FREQUENCY_LOW, 0x41 ; frekvence zvuku (komorni A = 440 Hz) db CHANNEL_1 + OPL_KEY_ON, 0x12 ; zapnuti/povoleni zvuku + nastaveni oktavy a vyssich bitu frekvence db 0, 0 ; zarazka perform_write_to_opl_register: ; zapis do vybraneho registru OPL2 nebo OPL3 ; AL - registr ; AH - hodnota mov dx, OPL_ADDRESS ; vyber registru pro modifikaci out dx, al mov al, ah ; zapis hodnoty do vybraneho registru mov dx, OPL_DATA out dx, al ret perform_write_to_opl_high_register: ; zapis do vybraneho "vyssiho" registru OPL3 ; AL - registr ; AH - hodnota mov dx, OPL_HIGH_ADDRESS ; vyber registru pro modifikaci out dx, al mov al, ah ; zapis hodnoty do vybraneho registru mov dx, OPL_HIGH_DATA out dx, al ret
10. Modifikace tvaru nosné vlny i modulátoru
Prozatím jsme po zapnutí FM syntézy měnili pouze tvar vlny pro první operátor. Při FM syntéze je tento operátor použit jako modulátor nosné vlny. Ovšem pochopitelně nám nic nebrání v tom, abychom pozměnili i tvar nosné vlny. U čipu OPL2 tedy máme k dispozici čtyři možné kombinace, u čipu OPL3 se jedná o 8×8=64 možných kombinací tvarů vln. V dalším demonstračním příkladu se tvar vlny modulátoru stále ovládá klávesami 1–8, kdežto tvar nosné vlny (carrier) se mění klávesami Q-I. V assembleru je vše realizováno následujícím způsobem:
.opak: in al, PPI_PORT_A ; cteni stisknute klavesy cmp al, KEY_SPACE ; test na stisk mezerniku jne .next_test_1 ; neni stisknut -> preskok write_opl_register CHANNEL_1 + OPL_KEY_ON, 0x32 ; povoleni KEY ON bitu jmp .opak .next_test_1: cmp al, KEY_SPACE + KEY_RELEASE ; test na pusteni mezerniku jne .next_test_2 ; neni pusten -> dalsi test write_opl_register CHANNEL_1 + OPL_KEY_ON, 0x12 ; zakaz KEY ON bitu jmp .opak .next_test_2: cmp al, KEY_1 ; test na numericke klavesy jb .next_test_3 ; hodnota "pod" kodem klavesy 1 cmp al, KEY_8 ja .next_test_3 ; hodnota "nad" kodem klavesy 8 mov bl, al ; makro prepisuje AL -> nemuzeme ho primo pouzit sub bl, KEY_1 write_opl_register CHANNEL_1_OPERATOR_1 + OPL_WAVE_SELECT, bl jmp .opak .next_test_3: cmp al, KEY_Q ; test na dalsi radu klaves jb .next_test_4 ; hodnota "pod" kodem klavesy Q cmp al, KEY_I ja .next_test_4 ; hodnota "nad" kodem klavesy I mov bl, al ; makro prepisuje AL -> nemuzeme ho primo pouzit sub bl, KEY_Q write_opl_register CHANNEL_1_OPERATOR_2 + OPL_WAVE_SELECT, bl jmp .opak .next_test_4:
11. Úplný zdrojový kód dnešního čtvrtého demonstračního příkladu
Další části příkladu se již nemění, takže se jen v krátkosti podívejme na jeho kód:
; Prehrani zakladniho tonu na kartach s cipem OPL3. ; Prepnuti do rezimu OPL3. ; Prepinani tvaru vlny pro generovani zvuku. ; Pojmenovani registru OPL3. ; Vetsi zpetna vazba (feedback). ; Ovladani KEY ON mezernikem ; Tvar vlny prvniho operatoru je rizen klavesami 1 az 8 ; Tvar vlny druheho operatoru je rizen klavesami Q az I ; Ukonceni aplikace stiskem ESC ; ; ; Tento demonstracni priklad je pouzity v serialu o programovani ; grafickych dem a her na PC v DOSu: ; https://www.root.cz/serialy/vyvoj-her-a-grafickych-dem-pro-platformu-pc/ ; ; ; preklad pomoci: ; nasm -f bin -o sounds_opl3_waveform_4.com sounds_opl3_waveform_4.asm ; ; nebo pouze: ; nasm -o sounds_opl3_waveform_4.com sounds_opl3_waveform_4.asm ;----------------------------------------------------------------------------- BITS 16 ; 16bitovy vystup pro DOS CPU 8086 ; specifikace pouziteho instrukcniho souboru ;----------------------------------------------------------------------------- ; registry karet s cipem OPL3 OPL_ADDRESS equ 0x220 OPL_DATA equ 0x221 OPL_HIGH_ADDRESS equ 0x222 OPL_HIGH_DATA equ 0x223 ; ridici registry OPL2 OPL_TEST_LSI equ 0x01 OPL_TIMER_1 equ 0x02 OPL_TIMER_2 equ 0x03 OPL_TIMER_CTRL equ 0x04 OPL_KBSPLIT equ 0x08 OPL_AMP_VIBRATO_EG equ 0x20 OPL_LEVEL equ 0x40 OPL_ATTACK_DECAY equ 0x60 OPL_SUSTAIN_RELEASE equ 0x80 OPL_FREQUENCY_LOW equ 0xa0 OPL_KEY_ON equ 0xb0 OPL_AM_VIBRATO_RHYTHM equ 0xbd OPL_FEEDBACK equ 0xc0 OPL_WAVE_SELECT equ 0xe0 OPL3_MODE_ENABLE equ 0x05 ; vyssi port!!! ; indexy kanalu CHANNEL_1 equ 0 CHANNEL_2 equ 1 CHANNEL_3 equ 2 CHANNEL_4 equ 3 CHANNEL_5 equ 4 CHANNEL_6 equ 5 CHANNEL_7 equ 6 CHANNEL_8 equ 7 CHANNEL_9 equ 8 ; offsety pro jednotlive operatory ; -------------------------------------------------- ; Channel 1 2 3 4 5 6 7 8 9 ; Operator 1 00 01 02 08 09 0A 10 11 12 ; Operator 2 03 04 05 0B 0C 0D 13 14 15 ; -------------------------------------------------- ; Channel 1 2 3 4 5 6 7 8 9 CHANNEL_1_OPERATOR_1 equ 0x00 CHANNEL_1_OPERATOR_2 equ 0x03 CHANNEL_2_OPERATOR_1 equ 0x01 CHANNEL_2_OPERATOR_2 equ 0x04 CHANNEL_3_OPERATOR_1 equ 0x02 CHANNEL_3_OPERATOR_2 equ 0x05 CHANNEL_4_OPERATOR_1 equ 0x08 CHANNEL_4_OPERATOR_2 equ 0x0b CHANNEL_5_OPERATOR_1 equ 0x09 CHANNEL_5_OPERATOR_2 equ 0x0c CHANNEL_6_OPERATOR_1 equ 0x0a CHANNEL_6_OPERATOR_2 equ 0x0d CHANNEL_7_OPERATOR_1 equ 0x10 CHANNEL_7_OPERATOR_2 equ 0x13 CHANNEL_8_OPERATOR_1 equ 0x11 CHANNEL_8_OPERATOR_2 equ 0x14 CHANNEL_9_OPERATOR_1 equ 0x12 CHANNEL_9_OPERATOR_2 equ 0x15 ; registry PPI PPI_PORT_A equ 0x60 PPI_PORT_B equ 0x61 ; kody klaves KEY_ESC equ 0x01 KEY_SPACE equ 0x39 KEY_RELEASE equ 0x80 KEY_1 equ 0x02 KEY_8 equ KEY_1 + 8 KEY_Q equ 0x10 KEY_W equ 0x11 KEY_E equ 0x12 KEY_R equ 0x13 KEY_T equ 0x14 KEY_Y equ 0x15 KEY_U equ 0x16 KEY_I equ 0x17 ;----------------------------------------------------------------------------- ; ukonceni procesu a navrat do DOSu %macro exit 0 ret %endmacro ; makro pro zapis do registru OPL2 nebo OPL3 %macro write_opl_register 2 mov al, %1 mov ah, %2 call perform_write_to_opl_register %endmacro ; makro pro zapis do "vyssiho" registru OPL3 %macro write_opl_high_register 2 mov al, %1 mov ah, %2 call perform_write_to_opl_high_register %endmacro ;----------------------------------------------------------------------------- org 0x100 ; zacatek kodu pro programy typu COM (vzdy se zacina na 256) start: push cs pop ds ; DS==CS write_opl_high_register OPL3_MODE_ENABLE, 1 mov si, tone1 ; zacatek tabulky call write_table_to_opl3 ; zapis obsahu tabulky do OPL3 in al, PPI_PORT_B ; port B s rizenim zarizeni or al, 0b1000000 ; nastaveni bitu cislo 7 na jednicku out PPI_PORT_B, al ; zapis zpet na port B .opak: in al, PPI_PORT_A ; cteni stisknute klavesy cmp al, KEY_SPACE ; test na stisk mezerniku jne .next_test_1 ; neni stisknut -> preskok write_opl_register CHANNEL_1 + OPL_KEY_ON, 0x32 ; povoleni KEY ON bitu jmp .opak .next_test_1: cmp al, KEY_SPACE + KEY_RELEASE ; test na pusteni mezerniku jne .next_test_2 ; neni pusten -> dalsi test write_opl_register CHANNEL_1 + OPL_KEY_ON, 0x12 ; zakaz KEY ON bitu jmp .opak .next_test_2: cmp al, KEY_1 ; test na numericke klavesy jb .next_test_3 ; hodnota "pod" kodem klavesy 1 cmp al, KEY_8 ja .next_test_3 ; hodnota "nad" kodem klavesy 8 mov bl, al ; makro prepisuje AL -> nemuzeme ho primo pouzit sub bl, KEY_1 write_opl_register CHANNEL_1_OPERATOR_1 + OPL_WAVE_SELECT, bl jmp .opak .next_test_3: cmp al, KEY_Q ; test na dalsi radu klaves jb .next_test_4 ; hodnota "pod" kodem klavesy Q cmp al, KEY_I ja .next_test_4 ; hodnota "nad" kodem klavesy I mov bl, al ; makro prepisuje AL -> nemuzeme ho primo pouzit sub bl, KEY_Q write_opl_register CHANNEL_1_OPERATOR_2 + OPL_WAVE_SELECT, bl jmp .opak .next_test_4: cmp al, KEY_ESC ; test stisknute klavesy ESC jne .opak ; neni stisknuta? -> zkusme znovu exit write_table_to_opl3: lodsb ; nacist bajt z tabulky (cislo registru) or al, al ; test na nulu jnz .write_register ret ; dosahli jsme konce tabulky .write_register: mov ah, al lodsb ; nacist dalsi bajt z tabulky (hodnota registru) xchg al, ah ; podprogram vyzaduje opacne poradi AL, AH call perform_write_to_opl_register jmp write_table_to_opl3 ; muzeme prejit na dalsi registr tone1: ; tabulka s tonem pro prvni kanal db CHANNEL_1_OPERATOR_1 + OPL_AMP_VIBRATO_EG, 0x01 ; nastaveni modulatoru: nasobeni frekvence jednickou db CHANNEL_1_OPERATOR_1 + OPL_LEVEL, 0x00 ; uroven vystupu 40 dB db CHANNEL_1_OPERATOR_1 + OPL_ATTACK_DECAY, 0x41 ; modulator: pomaly nastup zvuku + pomale doznivani db CHANNEL_1_OPERATOR_1 + OPL_SUSTAIN_RELEASE, 0x7f ; urovne sustain a release pro modulator db CHANNEL_1_OPERATOR_2 + OPL_AMP_VIBRATO_EG, 0x01 ; nastaveni nosne: nasobeni frekvence jednickou db CHANNEL_1_OPERATOR_2 + OPL_LEVEL, 0x00 ; nastaveni urovne vystupu nosne na 47 dB db CHANNEL_1_OPERATOR_2 + OPL_ATTACK_DECAY, 0xa2 ; nosna: rychly nastup + pomale doznivani db CHANNEL_1_OPERATOR_2 + OPL_SUSTAIN_RELEASE, 0x77 ; urovne sustain a release pro nosnou db CHANNEL_1_OPERATOR_1 + OPL_WAVE_SELECT, 0x00 ; standardni sinus db CHANNEL_1_OPERATOR_2 + OPL_WAVE_SELECT, 0x00 ; standardni sinus db CHANNEL_1 + OPL_FREQUENCY_LOW, 0x41 ; frekvence zvuku (komorni A = 440 Hz) db CHANNEL_1 + OPL_KEY_ON, 0x12 ; zapnuti/povoleni zvuku + nastaveni oktavy a vyssich bitu frekvence db 0, 0 ; zarazka perform_write_to_opl_register: ; zapis do vybraneho registru OPL2 nebo OPL3 ; AL - registr ; AH - hodnota mov dx, OPL_ADDRESS ; vyber registru pro modifikaci out dx, al mov al, ah ; zapis hodnoty do vybraneho registru mov dx, OPL_DATA out dx, al ret perform_write_to_opl_high_register: ; zapis do vybraneho "vyssiho" registru OPL3 ; AL - registr ; AH - hodnota mov dx, OPL_HIGH_ADDRESS ; vyber registru pro modifikaci out dx, al mov al, ah ; zapis hodnoty do vybraneho registru mov dx, OPL_HIGH_DATA out dx, al ret
12. Režim, ve kterém je jeden kanál tvořen čtyřmi operátory
Konečně se dostáváme k další důležité vlastnosti čipů OPL3. Tyto čipy totiž dokážou některé kanály spojit dohromady a získat tak kanály, které mají namísto pouhých dvou operátorů operátory čtyři. Ovšem nelze takto spojit všechny kanály – maximálně je možné dosáhnout stavu, že budeme mít k dispozici šest kanálů se čtyřmi operátory, přičemž zbytek kanálů je použit buď v dvouoperátorovém režimu nebo se využijí pro perkusní nástroje:
- 18 kanálů, z nichž každý obsahuje dva operátory („dvojitý“ OPL2)
- 15 melodických kanálů se dvěma operátory + pět kanálů pro perkusní režim
- Až 6 kanálů se čtyřmi operátory + zbytek (minimálně 6 kanálů) se dvěma operátory
- Až 6 kanálů se čtyřmi operátory + pět kanálů pro perkusní režim + zbytek kanály se dvěma operátory
Dnes se zaměříme na spojení prvního a druhého kanálu do nového kanálu se čtyřmi operátory. Zbytek nás nemusí zajímat – takže se vlastně pohybujeme ve třetí a čtvrté skupině.
13. Realizace spojení kanálů tak, aby byly k dispozici čtyři operátory
Ve výchozím nastavení je čip OPL3 přepnutý do režimu, ve kterém má každý kanál k dispozici pouze dva operátory a perkusní režim je zakázán. To v praxi znamená, že tón může být tvořen 18 kanály (celkový počet operátorů je stále roven 36), což jsme si již ostatně ukázali minule při naprogramování „kláves“ s 2×8 notami. Pokud budeme chtít některé kanály spojit takovým způsobem, aby se daly použít čtyři operátory, je nutné korektně nastavit registr 0×104, tedy registr z horní sady 256 řídicích registrů:
OPL_FOUR_OPERATOR_ENABLE equ 0x04 ; vyssi port!!!
V tomto registru má význam spodních šest bitů, protože můžeme vytvořit maximálně šest čtyřoperátorových kanálů:
Bit | Stručný popis |
---|---|
5 | spojení kanálů 12 a 15 |
4 | spojení kanálů 11 a 14 |
3 | spojení kanálů 10 a 13 |
2 | spojení kanálů 3 a 6 |
1 | spojení kanálů 2 a 5 |
0 | spojení kanálů 1 a 4 |
Spojení kanálů 1 a 4 realizujeme zavoláním makra:
write_opl_high_register OPL_FOUR_OPERATOR_ENABLE, 0b00000001
Offsety jednotlivých operátorů v kanálu se čtyřmi operátory se vypočtou podle tabulky:
; Channel 1 2 3 10 11 12 ; Operator 1 00 01 02 12 13 14 ; Operator 2 03 04 05 15 16 17 ; Operator 3 08 09 0a 18 19 1a ; Operator 4 0b 0c 0d 1b 1c 1d ; --------------------------------------------------
V našem konkrétním případě si tedy vystačíme s operátory 0, 3, 8 a 0×b.
14. Způsoby vzájemného propojení čtyř operátorů (algoritmy)
U již výše zmíněného syntetizéru Yamaha DX7 se používá označení algoritmus (viz též https://www.tinyloops.com/doc/yamaha_dx7/algorithm-building-blocks.html) pro nastavení způsobu vzájemného propojení operátorů. V případě čipu OPL3 ovšem nemáme k dispozici 6 operátorů, ale pouze čtyři operátory. Navíc si si ale můžeme vybrat, jaký typ syntézy (AM či FM) se bude realizovat. Jednotlivé způsoby propojení je možné vizualizovat následovně:
a) FM-FM Mode ┌───────┐ ┌───────┐ ┌───────┐ ┌───────┐ │ │ │ │ │ │ │ │ │ Op. 1 ├─────>│ Op. 2 ├─────>│ Op. 3 ├─────>│ Op. 4 ├─────> Output │ │ │ │ │ │ │ │ └───────┘ └───────┘ └───────┘ └───────┘ b) AM-FM Mode ┌───────┐ │ │ │ Op. 1 ├───────────────────────────────────┐ │ │ │ └───────┘ │ │ ┌───────┐ ┌───────┐ ┌───────┐ │ │ │ │ │ │ │ │ │ Op. 2 ├─────>│ Op. 3 ├─────>│ Op. 4 ├─────┴─────> Output │ │ │ │ │ │ └───────┘ └───────┘ └───────┘ c) FM-AM Mode ┌───────┐ ┌───────┐ │ │ │ │ │ Op. 1 ├─────>│ Op. 2 ├─────┐ │ │ │ │ │ └───────┘ └───────┘ │ ├─────> Output ┌───────┐ ┌───────┐ │ │ │ │ │ │ │ Op. 3 ├─────>│ Op. 4 ├─────┘ │ │ │ │ └───────┘ └───────┘ d) AM-AM Mode ┌───────┐ │ │ │ Op. 1 ├────────────────────┐ │ │ │ └───────┘ │ │ ┌───────┐ ┌───────┐ │ │ │ │ │ │ │ Op. 2 ├─────>│ Op. 3 ├─────┼─────> Output │ │ │ │ │ └───────┘ └───────┘ │ │ ┌───────┐ │ │ │ │ │ Op. 4 ├────────────────────┘ │ │ └───────┘
Zdroj: https://moddingwiki.shikadi.net/wiki/OPL_chip#Four-operator_%22Mess%22_Modulation_Synthesis.
15. Interaktivní přepínání AM a FM režimů u kanálu se čtyřmi operátory
V případě, že je první kanál nakonfigurován takovým způsobem, že je složen ze čtyř operátorů, volí se kombinace AM a FM syntézy s využitím registrů OPL_FEEDBACK rezervovaných pro první a čtvrtý kanál. Proč tomu tak je? „Čtyřoperátorový“ první kanál totiž vznikne spojením dvou původních „dvouoperátorových“ kanálů, a to konkrétně kanálů 1 a 4, což jsme si již ukázali v tabulce uvedené ve třinácté kapitole.
Volba AM/FM je vybírána nultým bitem registru OPL_FEEDBACK:
db CHANNEL_1 + OPL_FEEDBACK, 0b00110000 ; volba AM-FM db CHANNEL_1 + OPL_FEEDBACK + 3, 0b00110000 ; volba AM-FM
S významem (0 a 1 zde značí nultý bit registru OPL_FEEDBACK):
OPL_FEEDBACK | OPL_FEEDBACK+3 | Propojení operátorů |
---|---|---|
0 | 0 | FM-FM |
1 | 1 | AM-FM |
0 | 0 | FM-AM |
1 | 1 | AM-AM |
Tuto dvojici bitů budeme interaktivně ovládat klávesami 1 až 4 (1/2 – výběr prvního sloupce, 3/4 – výběr druhého sloupce). Samotná realizace je celkem snadná:
cmp al, KEY_1 jne .next_test_3 write_opl_register CHANNEL_1 + OPL_FEEDBACK, 0b00110000 ; FM jmp .opak .next_test_3: cmp al, KEY_2 jne .next_test_4 write_opl_register CHANNEL_1 + OPL_FEEDBACK, 0b00110001 ; AM jmp .opak .next_test_4: cmp al, KEY_3 jne .next_test_5 write_opl_register CHANNEL_1 + OPL_FEEDBACK + 3, 0b00110000 ; FM jmp .opak .next_test_5: cmp al, KEY_4 jne .next_test_6 write_opl_register CHANNEL_1 + OPL_FEEDBACK + 3, 0b00110001 ; AM jmp .opak .next_test_6:
16. Úplný zdrojový kód dnešního pátého demonstračního příkladu
Výše popsané interaktivní přepínání AM a FM režimů u jediného (prvního) kanálu nakonfigurovaného tak, že využívá čtyři operátory, je realizováno v dnešním posledním demonstračním příkladu, jehož zdrojový kód vypadá následovně:
; Prehrani tonu s vyuzitim 4 operatoru na kartach s cipem OPL3. ; Prepnuti do rezimu OPL3. ; Pojmenovani registru OPL3. ; Vetsi zpetna vazba (feedback). ; Ovladani KEY ON mezernikem ; Ukonceni aplikace stiskem ESC ; ; ; Tento demonstracni priklad je pouzity v serialu o programovani ; grafickych dem a her na PC v DOSu: ; https://www.root.cz/serialy/vyvoj-her-a-grafickych-dem-pro-platformu-pc/ ; ; ; preklad pomoci: ; nasm -f bin -o sounds_opl3_4operators_1.com sounds_opl3_4operators_1.asm ; ; nebo pouze: ; nasm -o sounds_opl3_4operators_1.com sounds_opl3_4operators_1.asm ;----------------------------------------------------------------------------- BITS 16 ; 16bitovy vystup pro DOS CPU 8086 ; specifikace pouziteho instrukcniho souboru ;----------------------------------------------------------------------------- ; registry karet s cipem OPL3 OPL_ADDRESS equ 0x220 OPL_DATA equ 0x221 OPL_HIGH_ADDRESS equ 0x222 OPL_HIGH_DATA equ 0x223 ; ridici registry OPL2 OPL_TEST_LSI equ 0x01 OPL_TIMER_1 equ 0x02 OPL_TIMER_2 equ 0x03 OPL_TIMER_CTRL equ 0x04 OPL_KBSPLIT equ 0x08 OPL_AMP_VIBRATO_EG equ 0x20 OPL_LEVEL equ 0x40 OPL_ATTACK_DECAY equ 0x60 OPL_SUSTAIN_RELEASE equ 0x80 OPL_FREQUENCY_LOW equ 0xa0 OPL_KEY_ON equ 0xb0 OPL_AM_VIBRATO_RHYTHM equ 0xbd OPL_FEEDBACK equ 0xc0 OPL_WAVE_SELECT equ 0xe0 OPL_FOUR_OPERATOR_ENABLE equ 0x04 ; vyssi port!!! OPL3_MODE_ENABLE equ 0x05 ; vyssi port!!! ; indexy kanalu CHANNEL_1 equ 0 CHANNEL_2 equ 1 CHANNEL_3 equ 2 CHANNEL_4 equ 3 CHANNEL_5 equ 4 CHANNEL_6 equ 5 CHANNEL_7 equ 6 CHANNEL_8 equ 7 CHANNEL_9 equ 8 ; offsety pro jednotlive operatory v rezimu dvou operatoru ; -------------------------------------------------- ; Channel 1 2 3 4 5 6 7 8 9 ; Operator 1 00 01 02 08 09 0A 10 11 12 ; Operator 2 03 04 05 0B 0C 0D 13 14 15 ; -------------------------------------------------- ; Channel 1 2 3 4 5 6 7 8 9 ; offsety pro jednotlive operatory v rezimu ctyr operatoru ; -------------------------------------------------- ; Channel 1 2 3 10 11 12 ; Operator 1 00 01 02 12 13 14 ; Operator 2 03 04 05 15 16 17 ; Operator 3 08 09 0a 18 19 1a ; Operator 4 0b 0c 0d 1b 1c 1d ; -------------------------------------------------- ; Channel 1 2 3 10 11 12 CHANNEL_1_OPERATOR_1 equ 0x00 CHANNEL_1_OPERATOR_2 equ 0x03 CHANNEL_1_OPERATOR_3 equ 0x08 CHANNEL_1_OPERATOR_4 equ 0x0b CHANNEL_2_OPERATOR_1 equ 0x01 CHANNEL_2_OPERATOR_2 equ 0x04 CHANNEL_3_OPERATOR_1 equ 0x02 CHANNEL_3_OPERATOR_2 equ 0x05 CHANNEL_4_OPERATOR_1 equ 0x08 CHANNEL_4_OPERATOR_2 equ 0x0b CHANNEL_5_OPERATOR_1 equ 0x09 CHANNEL_5_OPERATOR_2 equ 0x0c CHANNEL_6_OPERATOR_1 equ 0x0a CHANNEL_6_OPERATOR_2 equ 0x0d CHANNEL_7_OPERATOR_1 equ 0x10 CHANNEL_7_OPERATOR_2 equ 0x13 CHANNEL_8_OPERATOR_1 equ 0x11 CHANNEL_8_OPERATOR_2 equ 0x14 CHANNEL_9_OPERATOR_1 equ 0x12 CHANNEL_9_OPERATOR_2 equ 0x15 ; registry PPI PPI_PORT_A equ 0x60 PPI_PORT_B equ 0x61 ; kody klaves KEY_ESC equ 0x01 KEY_SPACE equ 0x39 KEY_RELEASE equ 0x80 KEY_1 equ 0x02 KEY_2 equ 0x03 KEY_3 equ 0x04 KEY_4 equ 0x05 ;----------------------------------------------------------------------------- ; ukonceni procesu a navrat do DOSu %macro exit 0 ret %endmacro ; makro pro zapis do registru OPL2 nebo OPL3 %macro write_opl_register 2 mov al, %1 mov ah, %2 call perform_write_to_opl_register %endmacro ; makro pro zapis do "vyssiho" registru OPL3 %macro write_opl_high_register 2 mov al, %1 mov ah, %2 call perform_write_to_opl_high_register %endmacro ;----------------------------------------------------------------------------- org 0x100 ; zacatek kodu pro programy typu COM (vzdy se zacina na 256) start: push cs pop ds ; DS==CS write_opl_high_register OPL3_MODE_ENABLE, 1 write_opl_high_register OPL_FOUR_OPERATOR_ENABLE, 0b00000001 mov si, tone1 ; zacatek tabulky call write_table_to_opl3 ; zapis obsahu tabulky do OPL3 in al, PPI_PORT_B ; port B s rizenim zarizeni or al, 0b1000000 ; nastaveni bitu cislo 7 na jednicku out PPI_PORT_B, al ; zapis zpet na port B .opak: in al, PPI_PORT_A ; cteni stisknute klavesy cmp al, KEY_SPACE ; test na stisk mezerniku jne .next_test_1 ; neni stisknut -> preskok write_opl_register CHANNEL_1 + OPL_KEY_ON, 0x32 ; povoleni KEY ON bitu jmp .opak .next_test_1: cmp al, KEY_SPACE + KEY_RELEASE ; test na pusteni mezerniku jne .next_test_2 ; neni pusten -> dalsi test write_opl_register CHANNEL_1 + OPL_KEY_ON, 0x12 ; zakaz KEY ON bitu jmp .opak .next_test_2: cmp al, KEY_1 jne .next_test_3 write_opl_register CHANNEL_1 + OPL_FEEDBACK, 0b00110000 ; FM jmp .opak .next_test_3: cmp al, KEY_2 jne .next_test_4 write_opl_register CHANNEL_1 + OPL_FEEDBACK, 0b00110001 ; AM jmp .opak .next_test_4: cmp al, KEY_3 jne .next_test_5 write_opl_register CHANNEL_1 + OPL_FEEDBACK + 3, 0b00110000 ; FM jmp .opak .next_test_5: cmp al, KEY_4 jne .next_test_6 write_opl_register CHANNEL_1 + OPL_FEEDBACK + 3, 0b00110001 ; AM jmp .opak .next_test_6: cmp al, KEY_ESC ; test stisknute klavesy ESC jne .opak ; neni stisknuta? -> zkusme znovu exit write_table_to_opl3: lodsb ; nacist bajt z tabulky (cislo registru) or al, al ; test na nulu jnz .write_register ret ; dosahli jsme konce tabulky .write_register: mov ah, al lodsb ; nacist dalsi bajt z tabulky (hodnota registru) xchg al, ah ; podprogram vyzaduje opacne poradi AL, AH call perform_write_to_opl_register jmp write_table_to_opl3 ; muzeme prejit na dalsi registr tone1: ; tabulka s tonem pro prvni kanal db CHANNEL_1_OPERATOR_1 + OPL_AMP_VIBRATO_EG, 0x01 ; nastaveni modulatoru: nasobeni frekvence jednickou db CHANNEL_1_OPERATOR_1 + OPL_LEVEL, 0x00 ; uroven vystupu 40 dB db CHANNEL_1_OPERATOR_1 + OPL_ATTACK_DECAY, 0x31 ; modulator: pomaly nastup zvuku + pomale doznivani db CHANNEL_1_OPERATOR_1 + OPL_SUSTAIN_RELEASE, 0x71 ; urovne sustain a release pro modulator db CHANNEL_1_OPERATOR_1 + OPL_WAVE_SELECT, 0x00 ; standardni sinus db CHANNEL_1_OPERATOR_2 + OPL_AMP_VIBRATO_EG, 0x01 ; nastaveni nosne: nasobeni frekvence jednickou db CHANNEL_1_OPERATOR_2 + OPL_LEVEL, 0x0f ; nastaveni urovne vystupu nosne na 47 dB db CHANNEL_1_OPERATOR_2 + OPL_ATTACK_DECAY, 0xa4 ; nosna: rychly nastup + pomale doznivani db CHANNEL_1_OPERATOR_2 + OPL_SUSTAIN_RELEASE, 0x71 ; urovne sustain a release pro nosnou db CHANNEL_1_OPERATOR_2 + OPL_WAVE_SELECT, 0x00 ; standardni sinus db CHANNEL_1_OPERATOR_3 + OPL_AMP_VIBRATO_EG, 0x01 ; nastaveni nosne: nasobeni frekvence jednickou db CHANNEL_1_OPERATOR_3 + OPL_LEVEL, 0x0f ; nastaveni urovne vystupu nosne na 47 dB db CHANNEL_1_OPERATOR_3 + OPL_ATTACK_DECAY, 0xa4 ; nosna: rychly nastup + pomale doznivani db CHANNEL_1_OPERATOR_3 + OPL_SUSTAIN_RELEASE, 0x71 ; urovne sustain a release pro nosnou db CHANNEL_1_OPERATOR_3 + OPL_WAVE_SELECT, 0x00 ; standardni sinus db CHANNEL_1_OPERATOR_4 + OPL_AMP_VIBRATO_EG, 0x01 ; nastaveni nosne: nasobeni frekvence jednickou db CHANNEL_1_OPERATOR_4 + OPL_LEVEL, 0x00 ; nastaveni urovne vystupu nosne na 47 dB db CHANNEL_1_OPERATOR_4 + OPL_ATTACK_DECAY, 0x44 ; nosna: rychly nastup + pomale doznivani db CHANNEL_1_OPERATOR_4 + OPL_SUSTAIN_RELEASE, 0x77 ; urovne sustain a release pro nosnou db CHANNEL_1_OPERATOR_4 + OPL_WAVE_SELECT, 0x00 ; standardni sinus db CHANNEL_1 + OPL_FREQUENCY_LOW, 0x41 ; frekvence zvuku (komorni A = 440 Hz) db CHANNEL_1 + OPL_KEY_ON, 0x12 ; zapnuti/povoleni zvuku + nastaveni oktavy a vyssich bitu frekvence db CHANNEL_1 + OPL_FEEDBACK, 0b00110000 ; volba AM-FM db CHANNEL_1 + OPL_FEEDBACK + 3, 0b00110000 ; volba AM-FM db 0, 0 ; zarazka perform_write_to_opl_register: ; zapis do vybraneho registru OPL2 nebo OPL3 ; AL - registr ; AH - hodnota mov dx, OPL_ADDRESS ; vyber registru pro modifikaci out dx, al mov al, ah ; zapis hodnoty do vybraneho registru mov dx, OPL_DATA out dx, al ret perform_write_to_opl_high_register: ; zapis do vybraneho "vyssiho" registru OPL3 ; AL - registr ; AH - hodnota mov dx, OPL_HIGH_ADDRESS ; vyber registru pro modifikaci out dx, al mov al, ah ; zapis hodnoty do vybraneho registru mov dx, OPL_HIGH_DATA out dx, al ret
17. Změna parametrů obálky v režimu se čtyřmi operátory
Rozdíl mezi AM a FM syntézou se ve skutečnosti projeví ve chvíli, kdy ještě více pozměníme obálky (ADSR) jednotlivých operátorů, které společně tvoří zvuk v prvním zvukovém kanálu. Poupravme tedy obálky takovým způsobem, aby měly velmi dlouhý dozvuk. Poté je již možné (a to opět klávesami 1–4) určovat způsob zapojení operátorů i zvolenou AM/FM syntézu (tedy všechny čtyři podporované kombinace neboli „algoritmy“):
; Prehrani tonu s vyuzitim 4 operatoru na kartach s cipem OPL3. ; Prepnuti do rezimu OPL3. ; Pojmenovani registru OPL3. ; Nastaveni pomaleho doznivani u vsech ctyr obalek. ; Ovladani KEY ON mezernikem ; Ukonceni aplikace stiskem ESC ; ; ; Tento demonstracni priklad je pouzity v serialu o programovani ; grafickych dem a her na PC v DOSu: ; https://www.root.cz/serialy/vyvoj-her-a-grafickych-dem-pro-platformu-pc/ ; ; ; preklad pomoci: ; nasm -f bin -o sounds_opl3_4operators_2.com sounds_opl3_4operators_2.asm ; ; nebo pouze: ; nasm -o sounds_opl3_4operators_2.com sounds_opl3_4operators_2.asm ;----------------------------------------------------------------------------- BITS 16 ; 16bitovy vystup pro DOS CPU 8086 ; specifikace pouziteho instrukcniho souboru ;----------------------------------------------------------------------------- ; registry karet s cipem OPL3 OPL_ADDRESS equ 0x220 OPL_DATA equ 0x221 OPL_HIGH_ADDRESS equ 0x222 OPL_HIGH_DATA equ 0x223 ; ridici registry OPL2 OPL_TEST_LSI equ 0x01 OPL_TIMER_1 equ 0x02 OPL_TIMER_2 equ 0x03 OPL_TIMER_CTRL equ 0x04 OPL_KBSPLIT equ 0x08 OPL_AMP_VIBRATO_EG equ 0x20 OPL_LEVEL equ 0x40 OPL_ATTACK_DECAY equ 0x60 OPL_SUSTAIN_RELEASE equ 0x80 OPL_FREQUENCY_LOW equ 0xa0 OPL_KEY_ON equ 0xb0 OPL_AM_VIBRATO_RHYTHM equ 0xbd OPL_FEEDBACK equ 0xc0 OPL_WAVE_SELECT equ 0xe0 OPL_FOUR_OPERATOR_ENABLE equ 0x04 ; vyssi port!!! OPL3_MODE_ENABLE equ 0x05 ; vyssi port!!! ; indexy kanalu CHANNEL_1 equ 0 CHANNEL_2 equ 1 CHANNEL_3 equ 2 CHANNEL_4 equ 3 CHANNEL_5 equ 4 CHANNEL_6 equ 5 CHANNEL_7 equ 6 CHANNEL_8 equ 7 CHANNEL_9 equ 8 ; offsety pro jednotlive operatory v rezimu dvou operatoru ; -------------------------------------------------- ; Channel 1 2 3 4 5 6 7 8 9 ; Operator 1 00 01 02 08 09 0A 10 11 12 ; Operator 2 03 04 05 0B 0C 0D 13 14 15 ; -------------------------------------------------- ; Channel 1 2 3 4 5 6 7 8 9 ; offsety pro jednotlive operatory v rezimu ctyr operatoru ; -------------------------------------------------- ; Channel 1 2 3 10 11 12 ; Operator 1 00 01 02 12 13 14 ; Operator 2 03 04 05 15 16 17 ; Operator 3 08 09 0a 18 19 1a ; Operator 4 0b 0c 0d 1b 1c 1d ; -------------------------------------------------- ; Channel 1 2 3 10 11 12 CHANNEL_1_OPERATOR_1 equ 0x00 CHANNEL_1_OPERATOR_2 equ 0x03 CHANNEL_1_OPERATOR_3 equ 0x08 CHANNEL_1_OPERATOR_4 equ 0x0b CHANNEL_2_OPERATOR_1 equ 0x01 CHANNEL_2_OPERATOR_2 equ 0x04 CHANNEL_3_OPERATOR_1 equ 0x02 CHANNEL_3_OPERATOR_2 equ 0x05 CHANNEL_4_OPERATOR_1 equ 0x08 CHANNEL_4_OPERATOR_2 equ 0x0b CHANNEL_5_OPERATOR_1 equ 0x09 CHANNEL_5_OPERATOR_2 equ 0x0c CHANNEL_6_OPERATOR_1 equ 0x0a CHANNEL_6_OPERATOR_2 equ 0x0d CHANNEL_7_OPERATOR_1 equ 0x10 CHANNEL_7_OPERATOR_2 equ 0x13 CHANNEL_8_OPERATOR_1 equ 0x11 CHANNEL_8_OPERATOR_2 equ 0x14 CHANNEL_9_OPERATOR_1 equ 0x12 CHANNEL_9_OPERATOR_2 equ 0x15 ; registry PPI PPI_PORT_A equ 0x60 PPI_PORT_B equ 0x61 ; kody klaves KEY_ESC equ 0x01 KEY_SPACE equ 0x39 KEY_RELEASE equ 0x80 KEY_1 equ 0x02 KEY_2 equ 0x03 KEY_3 equ 0x04 KEY_4 equ 0x05 ;----------------------------------------------------------------------------- ; ukonceni procesu a navrat do DOSu %macro exit 0 ret %endmacro ; makro pro zapis do registru OPL2 nebo OPL3 %macro write_opl_register 2 mov al, %1 mov ah, %2 call perform_write_to_opl_register %endmacro ; makro pro zapis do "vyssiho" registru OPL3 %macro write_opl_high_register 2 mov al, %1 mov ah, %2 call perform_write_to_opl_high_register %endmacro ;----------------------------------------------------------------------------- org 0x100 ; zacatek kodu pro programy typu COM (vzdy se zacina na 256) start: push cs pop ds ; DS==CS write_opl_high_register OPL3_MODE_ENABLE, 1 write_opl_high_register OPL_FOUR_OPERATOR_ENABLE, 0b00000001 mov si, tone1 ; zacatek tabulky call write_table_to_opl3 ; zapis obsahu tabulky do OPL3 in al, PPI_PORT_B ; port B s rizenim zarizeni or al, 0b1000000 ; nastaveni bitu cislo 7 na jednicku out PPI_PORT_B, al ; zapis zpet na port B .opak: in al, PPI_PORT_A ; cteni stisknute klavesy cmp al, KEY_SPACE ; test na stisk mezerniku jne .next_test_1 ; neni stisknut -> preskok write_opl_register CHANNEL_1 + OPL_KEY_ON, 0x32 ; povoleni KEY ON bitu jmp .opak .next_test_1: cmp al, KEY_SPACE + KEY_RELEASE ; test na pusteni mezerniku jne .next_test_2 ; neni pusten -> dalsi test write_opl_register CHANNEL_1 + OPL_KEY_ON, 0x12 ; zakaz KEY ON bitu jmp .opak .next_test_2: cmp al, KEY_1 jne .next_test_3 write_opl_register CHANNEL_1 + OPL_FEEDBACK, 0b00110000 ; FM jmp .opak .next_test_3: cmp al, KEY_2 jne .next_test_4 write_opl_register CHANNEL_1 + OPL_FEEDBACK, 0b00110001 ; AM jmp .opak .next_test_4: cmp al, KEY_3 jne .next_test_5 write_opl_register CHANNEL_1 + OPL_FEEDBACK + 3, 0b00110000 ; FM jmp .opak .next_test_5: cmp al, KEY_4 jne .next_test_6 write_opl_register CHANNEL_1 + OPL_FEEDBACK + 3, 0b00110001 ; AM jmp .opak .next_test_6: cmp al, KEY_ESC ; test stisknute klavesy ESC jne .opak ; neni stisknuta? -> zkusme znovu exit write_table_to_opl3: lodsb ; nacist bajt z tabulky (cislo registru) or al, al ; test na nulu jnz .write_register ret ; dosahli jsme konce tabulky .write_register: mov ah, al lodsb ; nacist dalsi bajt z tabulky (hodnota registru) xchg al, ah ; podprogram vyzaduje opacne poradi AL, AH call perform_write_to_opl_register jmp write_table_to_opl3 ; muzeme prejit na dalsi registr tone1: ; tabulka s tonem pro prvni kanal db CHANNEL_1_OPERATOR_1 + OPL_AMP_VIBRATO_EG, 0x01 ; nastaveni modulatoru: nasobeni frekvence jednickou db CHANNEL_1_OPERATOR_1 + OPL_LEVEL, 0x00 ; uroven vystupu 40 dB db CHANNEL_1_OPERATOR_1 + OPL_ATTACK_DECAY, 0x31 ; modulator: pomaly nastup zvuku + pomale doznivani db CHANNEL_1_OPERATOR_1 + OPL_SUSTAIN_RELEASE, 0x71 ; urovne sustain a release pro modulator db CHANNEL_1_OPERATOR_1 + OPL_WAVE_SELECT, 0x00 ; standardni sinus db CHANNEL_1_OPERATOR_2 + OPL_AMP_VIBRATO_EG, 0x01 ; nastaveni nosne: nasobeni frekvence jednickou db CHANNEL_1_OPERATOR_2 + OPL_LEVEL, 0x0f ; nastaveni urovne vystupu nosne na 47 dB db CHANNEL_1_OPERATOR_2 + OPL_ATTACK_DECAY, 0xa1 ; nosna: rychly nastup + pomale doznivani db CHANNEL_1_OPERATOR_2 + OPL_SUSTAIN_RELEASE, 0x71 ; urovne sustain a release pro nosnou db CHANNEL_1_OPERATOR_2 + OPL_WAVE_SELECT, 0x00 ; standardni sinus db CHANNEL_1_OPERATOR_3 + OPL_AMP_VIBRATO_EG, 0x01 ; nastaveni nosne: nasobeni frekvence jednickou db CHANNEL_1_OPERATOR_3 + OPL_LEVEL, 0x0f ; nastaveni urovne vystupu nosne na 47 dB db CHANNEL_1_OPERATOR_3 + OPL_ATTACK_DECAY, 0xa1 ; nosna: rychly nastup + pomale doznivani db CHANNEL_1_OPERATOR_3 + OPL_SUSTAIN_RELEASE, 0x71 ; urovne sustain a release pro nosnou db CHANNEL_1_OPERATOR_3 + OPL_WAVE_SELECT, 0x00 ; standardni sinus db CHANNEL_1_OPERATOR_4 + OPL_AMP_VIBRATO_EG, 0x01 ; nastaveni nosne: nasobeni frekvence jednickou db CHANNEL_1_OPERATOR_4 + OPL_LEVEL, 0x00 ; nastaveni urovne vystupu nosne na 47 dB db CHANNEL_1_OPERATOR_4 + OPL_ATTACK_DECAY, 0x41 ; nosna: rychly nastup + pomale doznivani db CHANNEL_1_OPERATOR_4 + OPL_SUSTAIN_RELEASE, 0x77 ; urovne sustain a release pro nosnou db CHANNEL_1_OPERATOR_4 + OPL_WAVE_SELECT, 0x00 ; standardni sinus db CHANNEL_1 + OPL_FREQUENCY_LOW, 0x41 ; frekvence zvuku (komorni A = 440 Hz) db CHANNEL_1 + OPL_KEY_ON, 0x12 ; zapnuti/povoleni zvuku + nastaveni oktavy a vyssich bitu frekvence db CHANNEL_1 + OPL_FEEDBACK, 0b00110001 ; volba AM-FM db CHANNEL_1 + OPL_FEEDBACK + 3, 0b00110001 ; volba AM-FM db 0, 0 ; zarazka perform_write_to_opl_register: ; zapis do vybraneho registru OPL2 nebo OPL3 ; AL - registr ; AH - hodnota mov dx, OPL_ADDRESS ; vyber registru pro modifikaci out dx, al mov al, ah ; zapis hodnoty do vybraneho registru mov dx, OPL_DATA out dx, al ret perform_write_to_opl_high_register: ; zapis do vybraneho "vyssiho" registru OPL3 ; AL - registr ; AH - hodnota mov dx, OPL_HIGH_ADDRESS ; vyber registru pro modifikaci out dx, al mov al, ah ; zapis hodnoty do vybraneho registru mov dx, OPL_HIGH_DATA out dx, al ret
18. Příloha: skript pro vykreslení sedmi signálů generovaných oscilátory čipu OPL3
Skript, kterým byly vykresleny obrázky 1 a 7 ve druhé a třetí kapitole, vypadá následovně:
import numpy as np import matplotlib.pyplot as plt from scipy import signal def plot(x, y, filename, title): # nastaveni os plt.xticks(ticks=np.floor(np.linspace(0, 511, 9))) plt.yticks(ticks=np.linspace(-1.5, 1.5, 7)) plt.xlim([0, 511]) plt.ylim([-1.5, 1.5]) # vykresleni plt.plot(x, y) # mrizka a dalsi parametry grafu plt.grid() plt.title(title) # ulozeni na disk plt.savefig(filename) # zobrazeni plt.show() plt.clf() # prubeh vlny x = np.linspace(0, 511, 200) y = np.sin(x * 2 * np.pi / 256.0) plot(x, y, "waveform_0.png", "Tvar vlny #0: sinus") # vynulovat zaporne hodnoty y[y < 0] = 0 plot(x, y, "waveform_1.png", "Tvar vlny #1: polovicni sinus") # absolutni hodnoty y = np.abs(np.sin(x * 2 * np.pi / 256.0)) plot(x, y, "waveform_2.png", "Tvar vlny #2: absolutni hodnoty sinu") # vynulovat liché periody y = np.abs(np.sin(x * 2 * np.pi / 256.0)) y2 = signal.square(4 * np.pi / 256.0 * x) y3 = y * y2 y3[y3 < 0] = 0 plot(x, y3, "waveform_3.png", "Tvar vlny #3: pulsní varianta") y = np.sin(x * 4 * np.pi / 256.0) y2 = signal.square(2 * np.pi / 256.0 * x) y2[y2 < 0] = 0 y3 = y * y2 plot(x, y3, "waveform_4.png", "Tvar vlny #4: jen sudé vlny") y = np.abs(np.sin(x * 4 * np.pi / 256.0)) y2 = signal.square(2 * np.pi / 256.0 * x) y2[y2 < 0] = 0 y3 = y * y2 plot(x, y3, "waveform_5.png", "Tvar vlny #5: jen sudé vlny, abs sin") # klasicky obdelnik y = signal.square(2 * np.pi / 256.0 * x) plot(x, y, "waveform_6.png", "Tvar vlny #6: obdélník")
19. Repositář s demonstračními příklady
Demonstrační příklady napsané v assembleru, které jsou určené pro překlad s využitím assembleru NASM, byly uloženy do Git repositáře, který je dostupný na adrese https://github.com/tisnik/8bit-fame. Jednotlivé demonstrační příklady si můžete v případě potřeby stáhnout i jednotlivě bez nutnosti klonovat celý (dnes již poměrně rozsáhlý) repositář:
# | Příklad | Stručný popis | Adresa |
---|---|---|---|
1 | hello.asm | program typu „Hello world“ naprogramovaný v assembleru pro systém DOS | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/hello.asm |
2 | hello_shorter.asm | kratší varianta výskoku z procesu zpět do DOSu | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/hello_shorter.asm |
3 | hello_wait.asm | čekání na stisk klávesy | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/hello_wait.asm |
4 | hello_macros.asm | realizace jednotlivých částí programu makrem | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/hello_macros.asm |
5 | gfx4_putpixel.asm | vykreslení pixelu v grafickém režimu 4 | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/gfx4_putpixel.asm |
6 | gfx6_putpixel.asm | vykreslení pixelu v grafickém režimu 6 | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/gfx6_putpixel.asm |
7 | gfx4_line.asm | vykreslení úsečky v grafickém režimu 4 | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/gfx4_line.asm |
8 | gfx6_line.asm | vykreslení úsečky v grafickém režimu 6 | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/gfx6_line.asm |
9 | gfx6_fill1.asm | vyplnění obrazovky v grafickém režimu, základní varianta | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/gfx6_fill1.asm |
10 | gfx6_fill2.asm | vyplnění obrazovky v grafickém režimu, varianta s instrukcí LOOP | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/gfx6_fill2.asm |
11 | gfx6_fill3.asm | vyplnění obrazovky instrukcí REP STOSB | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/gfx6_fill3.asm |
12 | gfx6_fill4.asm | vyplnění obrazovky, synchronizace vykreslování s paprskem | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/gfx6_fill4.asm |
13 | gfx4_image1.asm | vykreslení rastrového obrázku získaného z binárních dat, základní varianta | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/gfx4_image1.asm |
14 | gfx4_image2.asm | varianta vykreslení rastrového obrázku s využitím instrukce REP MOVSB | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/gfx4_image2.asm |
15 | gfx4_image3.asm | varianta vykreslení rastrového obrázku s využitím instrukce REP MOVSW | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/gfx4_image3.asm |
16 | gfx4_image4.asm | korektní vykreslení všech sudých řádků bitmapy | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/gfx4_image4.asm |
17 | gfx4_image5.asm | korektní vykreslení všech sudých i lichých řádků bitmapy | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/gfx4_image5.asm |
18 | gfx4_image6.asm | nastavení barvové palety před vykreslením obrázku | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/gfx4_image6.asm |
19 | gfx4_image7.asm | nastavení barvové palety před vykreslením obrázku, snížená intenzita barev | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/gfx4_image7.asm |
20 | gfx4_image8.asm | postupná změna barvy pozadí | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/gfx4_image8.asm |
21 | gfx6_putpixel1.asm | vykreslení pixelu, základní varianta se 16bitovým násobením | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/gfx6_putpixel1.asm |
22 | gfx6_putpixel2.asm | vykreslení pixelu, varianta s osmibitovým násobením | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/gfx6_putpixel2.asm |
23 | gfx6_putpixel3.asm | vykreslení pixelu, varianta bez násobení | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/gfx6_putpixel3.asm |
24 | gfx6_putpixel4.asm | vykreslení pixelu přes obrázek, nekorektní chování (přepis obrázku) | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/gfx6_putpixel4.asm |
25 | gfx6_putpixel5.asm | vykreslení pixelu přes obrázek, korektní varianta pro bílé pixely | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/gfx6_putpixel5.asm |
26 | cga_text_mode1.asm | standardní textový režim s rozlišením 40×25 znaků | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/cga_text_mode1.asm |
27 | cga_text_mode3.asm | standardní textový režim s rozlišením 80×25 znaků | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/cga_text_mode3.asm |
28 | cga_text_mode_intensity.asm | změna významu nejvyššího bitu atributového bajtu: vyšší intenzita namísto blikání | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/cga_text_mode_intensity.asm |
29 | cga_text_mode_cursor.asm | změna tvaru textového kurzoru | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/cga_text_mode_cursor.asm |
30 | cga_text_gfx1.asm | zobrazení „rastrové mřížky“: pseudografický režim 160×25 pixelů (interně textový režim) | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/cga_text_gfx1.asm |
31 | cga_text_mode_char_height.asm | změna výšky znaků | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/cga_text_mode_char_height.asm |
32 | cga_text_160×100.asm | grafický režim 160×100 se šestnácti barvami (interně upravený textový režim) | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/cga_text_160×100.asm |
33 | hercules_text_mode1.asm | využití standardního textového režimu společně s kartou Hercules | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/hercules_text_mode1.asm |
34 | hercules_text_mode2.asm | zákaz blikání v textových režimech | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/hercules_text_mode2.asm |
35 | hercules_turn_off.asm | vypnutí generování video signálu | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/hercules_turn_off.asm |
36 | hercules_gfx_mode1.asm | přepnutí karty Hercules do grafického režimu (základní varianta) | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/hercules_gfx_mode1.asm |
37 | hercules_gfx_mode2.asm | přepnutí karty Hercules do grafického režimu (vylepšená varianta) | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/hercules_gfx_mode2.asm |
38 | hercules_putpixel.asm | subrutina pro vykreslení jediného pixelu na kartě Hercules | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/hercules_putpixel.asm |
39 | ega_text_mode_80×25.asm | standardní textový režim 80×25 znaků na kartě EGA | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/ega_text_mode_80×25.asm |
40 | ega_text_mode_80×43.asm | zobrazení 43 textových řádků na kartě EGA | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/ega_text_mode_80×43.asm |
41 | ega_gfx_mode_320×200.asm | přepnutí do grafického režimu 320×200 pixelů se šestnácti barvami | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/ega_gfx_mode_320×200.asm |
42 | ega_gfx_mode_640×200.asm | přepnutí do grafického režimu 640×200 pixelů se šestnácti barvami | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/ega_gfx_mode_640×200.asm |
43 | ega_gfx_mode_640×350.asm | přepnutí do grafického režimu 640×350 pixelů se čtyřmi nebo šestnácti barvami | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/ega_gfx_mode_640×350.asm |
44 | ega_gfx_mode_bitplanes1.asm | ovládání zápisu do bitových rovin v planárních grafických režimech (základní způsob) | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/ega_gfx_mode_bitplanes1.asm |
45 | ega_gfx_mode_bitplanes2.asm | ovládání zápisu do bitových rovin v planárních grafických režimech (rychlejší způsob) | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/ega_gfx_mode_bitplanes2.asm |
46 | ega_320×200_putpixel.asm | vykreslení pixelu v grafickém režimu 320×200 pixelů se šestnácti barvami | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/ega_320×200_putpixel.asm |
47 | ega_640×350_putpixel.asm | vykreslení pixelu v grafickém režimu 640×350 pixelů se šestnácti barvami | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/ega_640×350_putpixel.asm |
48 | ega_standard_font.asm | použití standardního fontu grafické karty EGA | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/ega_standard_font.asm |
49 | ega_custom_font.asm | načtení vlastního fontu s jeho zobrazením | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/ega_custom_font.asm |
50 | ega_palette1.asm | změna barvové palety (všech 16 barev) v grafickém režimu 320×200 se šestnácti barvami | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/ega_palette1.asm |
51 | ega_palette2.asm | změna barvové palety (všech 16 barev) v grafickém režimu 640×350 se šestnácti barvami | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/ega_palette2.asm |
52 | ega_palette3.asm | změna všech barev v barvové paletě s využitím programové smyčky | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/ega_palette3.asm |
53 | ega_palette4.asm | změna všech barev, včetně barvy okraje, v barvové paletě voláním funkce BIOSu | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/ega_palette4.asm |
54 | vga_text_mode_80×25.asm | standardní textový režim 80×25 znaků na kartě VGA | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/vga_text_mode_80×25.asm |
55 | vga_text_mode_80×50.asm | zobrazení 50 a taktéž 28 textových řádků na kartě VGA | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/vga_text_mode_80×50.asm |
56 | vga_text_mode_intensity1.asm | změna chování atributového bitu pro blikání (nebezpečná varianta změny registrů) | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/vga_text_mode_intensity1.asm |
57 | vga_text_mode_intensity2.asm | změna chování atributového bitu pro blikání (bezpečnější varianta změny registrů) | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/vga_text_mode_intensity2.asm |
58 | vga_text_mode_9th_column.asm | modifikace způsobu zobrazení devátého sloupce ve znakových režimech (720 pixelů na řádku) | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/vga_text_mode_9th_column.asm |
59 | vga_text_mode_cursor_shape.asm | změna tvaru textového kurzoru na grafické kartě VGA | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/vga_text_mode_cursor_shape.asm |
60 | vga_text_mode_custom_font.asm | načtení vlastního fontu s jeho zobrazením | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/vga_text_mode_custom_font.asm |
61 | vga_gfx_mode_640×480.asm | přepnutí do grafického režimu 640×480 pixelů se šestnácti barvami, vykreslení vzorků | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/vga_gfx_mode_640×480.asm |
62 | vga_gfx_mode_320×200.asm | přepnutí do grafického režimu 320×200 pixelů s 256 barvami, vykreslení vzorků | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/vga_gfx_mode_320×200.asm |
63 | vga_gfx_mode_palette.asm | změna všech barev v barvové paletě grafické karty VGA | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/vga_gfx_mode_palette.asm |
64 | vga_gfx_mode_dac1.asm | využití DAC (neočekávané výsledky) | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/vga_gfx_mode_dac1.asm |
65 | vga_gfx_mode_dac2.asm | využití DAC (očekávané výsledky) | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/vga_gfx_mode_dac2.asm |
66 | vga_640×480_putpixel.asm | realizace algoritmu pro vykreslení pixelu v grafickém režimu 640×480 pixelů se šestnácti barvami | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/vga_640×480_putpixel.asm |
67 | vga_320×200_putpixel1.asm | realizace algoritmu pro vykreslení pixelu v grafickém režimu 320×200 s 256 barvami (základní varianta) | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/vga_320×200_putpixel1.asm |
68 | vga_320×200_putpixel2.asm | realizace algoritmu pro vykreslení pixelu v grafickém režimu 320×200 s 256 barvami (rychlejší varianta) | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/vga_320×200_putpixel2.asm |
69 | vga_gfx_mode_dac3.asm | přímé využití DAC v grafickém režimu 13h | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/vga_gfx_mode_dac3.asm |
70 | vga_gfx_mode_unchained_step1.asm | zobrazení barevných pruhů v režimu 13h | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/vga_gfx_mode_unchained_step1.asm |
71 | vga_gfx_mode_unchained_step2.asm | vypnutí zřetězení bitových rovin a změna způsobu adresování pixelů | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/vga_gfx_mode_unchained_step2.asm |
72 | vga_gfx_mode_unchained_step3.asm | vykreslení barevných pruhů do vybraných bitových rovin | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/vga_gfx_mode_unchained_step3.asm |
73 | vga_gfx_mode_320×400.asm | nestandardní grafický režim s rozlišením 320×400 pixelů a 256 barvami | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/vga_gfx_mode_320×400.asm |
74 | vga_320×200_image.asm | zobrazení rastrového obrázku ve standardním grafickém režimu 320×200 pixelů | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/vga_320×200_image.asm |
75 | vga_320×200_unchained_image1.asm | zobrazení rastrového obrázku v režimu s nezřetězenými rovinami (nekorektní řešení) | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/vga_320×200_unchained_image1.asm |
76 | vga_320×200_unchained_image2.asm | zobrazení rastrového obrázku v režimu s nezřetězenými rovinami (korektní řešení) | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/vga_320×200_unchained_image2.asm |
77 | vga_320×400_unchained_image.asm | zobrazení rastrového obrázku v nestandardním režimu 320×400 pixelů | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/vga_320×400_unchained_image.asm |
78 | vga_vertical_scroll1.asm | vertikální scrolling na kartě VGA v režimu s rozlišením 320×200 pixelů | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/vga_vertical_scroll1.asm |
79 | vga_vertical_scroll2.asm | vertikální scrolling na kartě VGA v režimu s rozlišením 320×400 pixelů | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/vga_vertical_scroll2.asm |
80 | vga_split_screen1.asm | režim split-screen a scrolling, nefunční varianta | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/vga_split_screen1.asm |
81 | vga_split_screen2.asm | režim split-screen a scrolling, plně funkční varianta | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/vga_split_screen2.asm |
82 | vga_horizontal_scroll1.asm | horizontální scrolling bez rozšíření počtu pixelů na virtuálním řádku | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/vga_horizontal_scroll1.asm |
83 | vga_horizontal_scroll2.asm | horizontální scrolling s rozšířením počtu pixelů na virtuálním řádku | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/vga_horizontal_scroll2.asm |
84 | vga_horizontal_scroll3.asm | jemný horizontální scrolling s rozšířením počtu pixelů na virtuálním řádku | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/vga_horizontal_scroll3.asm |
85 | vga_320×240_image.asm | nastavení grafického režimu Mode-X, načtení a vykreslení obrázku, scrolling | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/vga_320×240_image.asm |
86 | io.asm | knihovna maker pro I/O operace | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/io.asm |
87 | vga_lib.asm | knihovna maker a podprogramů pro programování karty VGA | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/vga_lib.asm |
88 | vga_320×240_lib.asm | nastavení grafického režimu Mode-X, tentokrát knihovními funkcemi | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/vga_320×240_lib.asm |
89 | vga_bitblt1.asm | první (naivní) implementace operace BitBLT | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/vga_bitblt1.asm |
90 | vga_bitblt2.asm | operace BitBLT s výběrem bitových rovin pro zápis | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/vga_bitblt2.asm |
91 | vga_bitblt3.asm | operace BitBLT s výběrem bitových rovin pro čtení i zápis | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/vga_bitblt3.asm |
92 | vga_bitblt4.asm | korektní BitBLT pro 16barevný režim, realizace makry | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/vga_bitblt4.asm |
93 | vga_bitblt5.asm | korektní BitBLT pro 16barevný režim, realizace podprogramem | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/vga_bitblt5.asm |
94 | vga_bitblt_rotate.asm | zápisový režim s rotací bajtu | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/vga_bitblt_rotate.asm |
95 | vga_bitblt_fast.asm | rychlá korektní 32bitová operace typu BitBLT | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/vga_bitblt_fast.asm |
96 | vga_320×400_bitblt1.asm | přenos obrázku v režimu 320×400 operací BitBLT (neúplná varianta) | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/vga_320×400_bitblt1.asm |
97 | vga_320×400_bitblt2.asm | přenos obrázku v režimu 320×400 operací BitBLT (úplná varianta) | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/vga_320×400_bitblt2.asm |
98 | vga_write_modes1.asm | volitelné zápisové režimy grafické karty VGA, zápis bez úpravy latche | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/vga_write_modes1.asm |
99 | vga_write_modes2.asm | volitelné zápisové režimy grafické karty VGA, zápis s modifikací latche | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/vga_write_modes2.asm |
100 | vga_write_modes3.asm | volitelné zápisové režimy grafické karty VGA, cílená modifikace latche vzorkem | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/vga_write_modes3.asm |
101 | instruction_jump.asm | použití instrukce JMP | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/instruction_jump.asm |
102 | instruction_jnz.asm | použití instrukce JNZ pro realizaci programové smyčky | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/instruction_jnz.asm |
103 | instruction_jz_jmp.asm | použití instrukcí JZ a JMP pro realizaci programové smyčky | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/instruction_jz_jmp.asm |
104 | instruction_loop.asm | použití instrukce LOOP pro realizaci programové smyčky | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/instruction_loop.asm |
105 | instruction_template.asm | šablona všech následujících demonstračních příkladů | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/instruction_template.asm |
106 | instruction_print_hex.asm | tisk osmibitové hexadecimální hodnoty | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/instruction_print_hex.asm |
107 | instruction_xlat.asm | využití instrukce XLAT pro získání tisknutelné hexadecimální cifry | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/instruction_xlat.asm |
108 | instruction_daa.asm | operace součtu s využitím binární i BCD aritmetiky | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/instruction_daa.asm |
109 | instruction_daa_sub.asm | instrukce DAA po provedení operace rozdílu | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/instruction_daa_sub.asm |
110 | instruction_das.asm | instrukce DAS po provedení operace rozdílu | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/instruction_das.asm |
111 | instruction_aaa.asm | korekce výsledku na jedinou BCD cifru operací AAA | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/instruction_aaa.asm |
112 | instruction_mul.asm | ukázka výpočtu součinu dvou osmibitových hodnot | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/instruction_mul.asm |
113 | instruction_aam.asm | BCD korekce po výpočtu součinu instrukcí AAM | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/instruction_aam.asm |
114 | instruction_stosb.asm | blokový zápis dat instrukcí STOSB | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/instruction_stosb.asm |
115 | instruction_rep_stosb.asm | opakované provádění instrukce STOSB | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/instruction_rep_stosb.asm |
116 | instruction_lodsb.asm | čtení dat instrukcí LODSB | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/instruction_lodsb.asm |
117 | instruction_movsb.asm | přenos jednoho bajtu instrukcí MOVSB | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/instruction_movsb.asm |
118 | instruction_rep_movsb.asm | blokový přenos po bajtech instrukcí MOVSB | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/instruction_rep_movsb.asm |
119 | instruction_rep_scas.asm | vyhledávání v řetězci instrukcí SCAS | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/instruction_rep_scas.asm |
120 | vga_320×200_image_0B.asm | výsledek blokového přenosu ve chvíli, kdy je CX=0 | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/vga_320×200_image_0B.asm |
121 | vga_320×200_image_64kB.asm | výsledek blokového přenosu ve chvíli, kdy je CX=0×ffff | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/vga_320×200_image_64kB.asm |
122 | vga_320×200_image_movsb.asm | blokový přenos v rámci obrazové paměti instrukcí REP MOVSB | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/vga_320×200_image_movsb.asm |
123 | vga_320×200_image_movsw.asm | blokový přenos v rámci obrazové paměti instrukcí REP MOVSW | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/vga_320×200_image_movsw.asm |
124 | vga_320×200_image_movsd.asm | blokový přenos v rámci obrazové paměti instrukcí REP MOVSD | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/vga_320×200_image_movsd.asm |
125 | vga_320×200_image_movsb_forward.asm | blokový přenos překrývajících se bloků paměti (zvyšující se adresy) | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/vga_320×200_image_movsb_forward.asm |
126 | vga_320×200_image_movsb_backward1.asm | blokový přenos překrývajících se bloků paměti (snižující se adresy, nekorektní nastavení) | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/vga_320×200_image_movsb_backward1.asm |
127 | vga_320×200_image_movsb_backward2.asm | blokový přenos překrývajících se bloků paměti (snižující se adresy, korektní nastavení) | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/vga_320×200_image_movsb_backward2.asm |
128 | sound_bell.asm | přehrání zvuku pomocí tisku ASCII znaku BELL | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/sound_bell.asm |
129 | sound_beep.asm | přehrání zvuku o zadané frekvenci na PC Speakeru | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/sound_beep.asm |
130 | sound_play_pitch.asm | přehrání zvuku o zadané frekvenci na PC Speakeru, použití maker | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/sound_play_pitch.asm |
131 | sound_opl2_basic.asm | přehrání komorního A na OPL2 | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/sound_opl2_basic.asm |
132 | sound_opl2_table.asm | přehrání komorního A na OPL2, použití tabulky s hodnotami registrů | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/sound_opl2_table.asm |
133 | sound_opl2_table2.asm | přepis tabulky s obsahy registrů pro přehrání komorního A | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/sound_opl2_table2.asm |
134 | sound_key_on.asm | přímé ovládání bitu KEY ON mezerníkem | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/sound_key_on.asm |
135 | sound_adsr.asm | nastavení obálky pro tón přehrávaný prvním kanálem | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/sound_adsr.asm |
136 | sound_modulation.asm | řízení frekvence modulátoru klávesami 1 a 0 | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/sound_modulation.asm |
137 | keyboard_basic.asm | přímá práce s klávesnicí IBM PC | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/keyboard_basic.asm |
138 | sound_stereo_opl2.asm | stereo zvuk v konfiguraci DualOPL2 | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/sound_stereo_opl2.asm |
139 | sound_opl2_multichannel.asm | vícekanálový zvuk na OPL2 (klávesy), delší varianta | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/sound_opl2_multichannel.asm |
140 | sound_opl2_multichannel2.asm | vícekanálový zvuk na OPL2 (klávesy), kratší varianta | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/sound_opl2_multichannel2.asm |
141 | sound_opl3_stereo1.asm | stereo výstup na OPL3 (v kompatibilním režimu) | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/sound_opl3_stereo1.asm |
142 | sound_opl3_stereo2.asm | stereo výstup na OPL3 (v režimu OPL3) | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/sound_opl3_stereo2.asm |
143 | sound_opl3_multichannel.asm | vícekanálový zvuk na OPL3 (klávesy) | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/sound_opl3_multichannel.asm |
144 | sound_opl3_waveform1.asm | interaktivní modifikace tvaru vlny u prvního operátoru | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/sound_opl3_waveform1.asm |
145 | sound_opl3_waveform2.asm | oprava chyby: povolení režimu kompatibilního s OPL3 | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/sound_opl3_waveform2.asm |
146 | sound_opl3_waveform3.asm | vliv tvaru vln na zvukový kanál s FM syntézou | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/sound_opl3_waveform3.asm |
147 | sound_opl3_waveform4.asm | modifikace tvaru vlny nosné vlny i modulátoru | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/sound_opl3_waveform4.asm |
148 | sound_opl3_4operators1.asm | výběr AM/FM režimu ve čtyřoperátorovém nastavení | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/sound_opl3_4operators1.asm |
149 | sound_opl3_4operators2.asm | výběr AM/FM režimu ve čtyřoperátorovém nastavení | https://github.com/tisnik/8bit-fame/blob/master/pc-dos/sound_opl3_4operators2.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 - How to use „AND,“ „OR,“ and „XOR“ modes for VGA Drawing
https://retrocomputing.stackexchange.com/questions/21936/how-to-use-and-or-and-xor-modes-for-vga-drawing - VGA Hardware
https://wiki.osdev.org/VGA_Hardware - Programmer's Guide to Yamaha YMF 262/OPL3 FM Music Synthesizer
https://moddingwiki.shikadi.net/wiki/OPL_chip - Does anybody understand how OPL2 percussion mode works?
https://forum.vcfed.org/index.php?threads/does-anybody-understand-how-opl2-percussion-mode-works.60925/ - Yamaha YMF262 OPL3 music – MoonDriver for OPL3 DEMO [Oscilloscope View]
https://www.youtube.com/watch?v=a7I-QmrkAak - Yamaha OPL vs OPL2 vs OPL3 comparison
https://www.youtube.com/watch?v=5knetge5Gs0 - OPL3 Music Crockett's Theme
https://www.youtube.com/watch?v=HXS008pkgSQ - Bad Apple (Adlib Tracker – OPL3)
https://www.youtube.com/watch?v=2lEPH6Y3Luo - FM Synthesis Chips, Codecs and DACs
https://www.dosdays.co.uk/topics/fm_synthesizers.php - The Zen Challenge – YMF262 OPL3 Original (For an upcoming game)
https://www.youtube.com/watch?v=6JlFIFz1CFY - [adlib tracker II techno music – opl3] orbit around alpha andromedae I
https://www.youtube.com/watch?v=YqxJCu_WFuA - [adlib tracker 2 music – opl3 techno] hybridisation process on procyon-ii
https://www.youtube.com/watch?v=daSV5mN0sJ4 - Hyper Duel – Black Rain (YMF262 OPL3 Cover)
https://www.youtube.com/watch?v=pu_mzRRq8Ho - IBM 5155–5160 Technical Reference
https://www.minuszerodegrees.net/manuals/IBM/IBM_5155_5160_Technical_Reference_6280089_MAR86.pdf - a ymf262/opl3+pc speaker thing i made
https://www.youtube.com/watch?v=E-Mx0lEmnZ0 - [OPL3] Like a Thunder
https://www.youtube.com/watch?v=MHf06AGr8SU - (PC SPEAKER) bad apple
https://www.youtube.com/watch?v=LezmKIIHyUg - Powering devices from PC parallel port
http://www.epanorama.net/circuits/lptpower.html - Magic Mushroom (demo pro PC s DOSem)
http://www.crossfire-designs.de/download/articles/soundcards//mushroom.rar - Píseň Magic Mushroom – originál
http://www.crossfire-designs.de/download/articles/soundcards/speaker_mushroom_converted.mp3 - Píseň Magic Mushroom – hráno na PC Speakeru
http://www.crossfire-designs.de/download/articles/soundcards/speaker_mushroom_speaker.mp3 - Pulse Width Modulation (PWM) Simulation Example
http://decibel.ni.com/content/docs/DOC-4599 - Resistor/Pulse Width Modulation DAC
http://www.k9spud.com/traxmod/pwmdac.php - Class D Amplifier
http://en.wikipedia.org/wiki/Electronic_amplifier#Class_D - Covox Speech Thing / Disney Sound Source (1986)
http://www.crossfire-designs.de/index.php?lang=en&what=articles&name=showarticle.htm&article=soundcards/&page=5 - Covox Digital-Analog Converter (Rusky, obsahuje schémata)
http://phantom.sannata.ru/konkurs/netskater002.shtml - PC-GPE on the Web
http://bespin.org/~qz/pc-gpe/ - Keyboard Synthesizer
http://www.solarnavigator.net/music/instruments/keyboards.htm - FMS – Fully Modular Synthesizer
http://fmsynth.sourceforge.net/ - Javasynth
http://javasynth.sourceforge.net/ - Software Sound Synthesis & Music Composition Packages
http://www.linux-sound.org/swss.html - Mx44.1 Download Page (software synthesizer for linux)
http://hem.passagen.se/ja_linux/ - Software synthesizer
http://en.wikipedia.org/wiki/Software_synthesizer - Frequency modulation synthesis
http://en.wikipedia.org/wiki/Frequency_modulation_synthesis - Yamaha DX7
http://en.wikipedia.org/wiki/Yamaha_DX7 - Wave of the Future
http://www.wired.com/wired/archive/2.03/waveguides_pr.html - Analog synthesizer
http://en.wikipedia.org/wiki/Analog_synthesizer - Minimoog
http://en.wikipedia.org/wiki/Minimoog - Moog synthesizer
http://en.wikipedia.org/wiki/Moog_synthesizer - Tutorial for Frequency Modulation Synthesis
http://www.sfu.ca/~truax/fmtut.html - An Introduction To FM
http://ccrma.stanford.edu/software/snd/snd/fm.html - John Chowning
http://en.wikipedia.org/wiki/John_Chowning - I'm Impressed, Adlib Music is AMAZING!
https://www.youtube.com/watch?v=PJNjQYp1ras - Milinda- Diode Milliampere ( OPL3 )
https://www.youtube.com/watch?v=oNhazT5HG0E - Dune 2 – Roland MT-32 Soundtrack
https://www.youtube.com/watch?v=kQADZeB-z8M