Obsah
1. Pojmenování řídicích registrů čipu OPL2
3. Přepis tabulky s obsahy registrů pro přehrání komorního A
4. První demonstrační příklad: upravené přehrání komorního A
6. Klávesnice IBM PC, čtení scan kódů kláves
7. Realizace aktivního čekání na stisk klávesy
8. Poznámka na okraj: rozeskok podle kódu stisknuté klávesy
9. Druhý demonstrační příklad – aktivní čekání na stisk klávesy ESC
10. Ovládání bitu KEY ON z klávesnice
11. Třetí demonstrační příklad: přímé ovládání bitu KEY ON mezerníkem
12. Nastavení obálky pro tón přehrávaný prvním kanálem
13. Čtvrtý demonstrační příklad: přehrání tónu s modifikovanými obálkami ADSR
14. Řízení změny frekvence výstupního tónu numerickými klávesami
15. Pátý demonstrační příklad: řízení frekvence modulátoru při přehrávání
16. Výsledné zvuky produkované demonstračními příklady
19. Repositář s demonstračními příklady
1. Pojmenování řídicích registrů čipu OPL2
Dnes navážeme na předchozí článek, v němž jsme si vysvětlili především způsob tvorby zvuků s využitím frekvenční, resp. v tomto případě přesněji fázové syntézy, popsali jsme si základní vlastnosti čipu OPL2 a taktéž jsme ho naprogramovali tak, aby dokázal přehrát komorní A. Nyní se pokusíme využít OPL2 pro tvorbu složitějších zvuků. Nejprve ale bude vhodné si z důvodu větší čitelnosti zdrojových kódů pojmenovat všechny řídicí registry čipu OPL2. Jak již víme, je těchto registrů velké množství a mnohé z nich jsou určeny pro ovládání konkrétních operátorů či celých kanálů:
Registr/registry | Oficiální jméno |
---|---|
01 | Test LSI / Enable waveform control |
02 | Timer 1 data (viz kapitolu 5) |
03 | Timer 2 data (viz kapitolu 5) |
04 | Timer control flags (viz kapitolu 5) |
08 | Speech synthesis mode / Keyboard split note select |
20..35 | Amp Mod / Vibrato / EG type / Key Scaling / Multiple |
40..55 | Key scaling level / Operator output level |
60..75 | Attack Rate / Decay Rate |
80..95 | Sustain Level / Release Rate |
A0..A8 | Frequency (low 8 bits) |
B0..B8 | Key On / Octave / Frequency (high 2 bits) |
BD | AM depth / Vibrato depth / Rhythm control |
C0..C8 | Feedback strength / Connection type |
E0..F5 | Wave Select |
Nadefinujme si tedy nejprve konstanty pro pojmenování všech registrů tak, jak to odpovídá prvnímu kanálu, popř. prvnímu operátoru tohoto kanálu (tj. budeme vždy používat dolní mez z rozsahu z předchozí tabulky). Tato jména zkombinujeme s offsety kanálů, popř. operátorů, což je ovšem téma navazující kapitoly:
; 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
2. Offsety kanálů a operátorů
Nyní si nadefinujeme offsety kanálů, což je snadné, protože tyto offsety tvoří souvislou řadu:
; 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
Příkladem registru (registrů), které jsou určeny pro řízení celých kanálů, je registr OPL_FREQUENCY_LOW (spodních osm bitů frekvence). Tento registr existuje celkem devětkrát (pro každý kanál zvlášť – kanálů je devět) a jeho adresu získáme snadno:
OPL_FREQUENCY_LOW + CHANNEL_1 OPL_FREQUENCY_LOW + CHANNEL_2 OPL_FREQUENCY_LOW + CHANNEL_3 OPL_FREQUENCY_LOW + CHANNEL_4 OPL_FREQUENCY_LOW + CHANNEL_5 OPL_FREQUENCY_LOW + CHANNEL_6 OPL_FREQUENCY_LOW + CHANNEL_7 OPL_FREQUENCY_LOW + CHANNEL_8 OPL_FREQUENCY_LOW + CHANNEL_9
A poslední sadou offsetů jsou offsety pro jednotlivé operátory. Zde již není situace tak přehledná, protože mapování mezi kanálem a jeho prvním nebo druhým operátorem netvoří souvislou řadu, což je patrné z následující tabulky:
; 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 ; --------------------------------------------------
Opět si tedy jednotlivé offsety nadefinujeme:
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
Následuje příklad použití pro registr OPL_LEVEL, jenž existuje celkem osmnáckrát (devět kanálů krát dva operátory):
OPL_LEVEL + CHANNEL_1_OPERATOR_1 OPL_LEVEL + CHANNEL_1_OPERATOR_2 ... ... ... OPL_LEVEL + CHANNEL_9_OPERATOR_1 OPL_LEVEL + CHANNEL_9_OPERATOR_2
3. Přepis tabulky s obsahy registrů pro přehrání komorního A
Tabulku s hodnotami registrů, které je nutné naplnit tak, aby čip OPL2 přehrál komorní A (440 Hz), si můžeme přepsat do nepatrně čitelnější podoby, kdy konkrétní adresy registrů OPL2 nahradíme za jejich jména. Připomeňme si, že původní podoba této tabulky vypadala následovně:
tone1: ; tabulka s tonem pro prvni kanal db 0x20, 0x01 ; nastaveni modulatoru: nasobeni frekvence jednickou db 0x40, 0x10 ; uroven vystupu 40 dB db 0x60, 0xF0 ; modulator: rychly nastup zvuku + pomale doznivani db 0x80, 0x77 ; urovne sustain a release pro modulator db 0xA0, 0x41 ; frekvence zvuku (komorni A = 440 Hz) db 0x23, 0x01 ; nastaveni nosne: nasobeni frekvence jednickou db 0x43, 0x00 ; nastavni urovne vystupu nosne na 47 dB db 0x63, 0xF0 ; nosna: rychly nastup + pomale doznivani db 0x83, 0x77 ; urovne sustain a release pro nosnou db 0xB0, 0x32 ; zapnuti/povoleni zvuku + nastaveni oktavy a vyssich bitu frekvence db 0, 0 ; zarazka
Po přepisu s využitím adres registrů a offsetů kanálů, resp. operátorů dostaneme:
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, 0x10 ; uroven vystupu 40 dB db CHANNEL_1_OPERATOR_1 + OPL_ATTACK_DECAY, 0xF0 ; modulator: rychly nastup zvuku + pomale doznivani db CHANNEL_1_OPERATOR_1 + OPL_SUSTAIN_RELEASE, 0x77 ; urovne sustain a release pro modulator db CHANNEL_1_OPERATOR_1 + OPL_FREQUENCY_LOW, 0x41 ; frekvence zvuku (komorni A = 440 Hz) 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 + OPL_KEY_ON, 0x32 ; zapnuti/povoleni zvuku + nastaveni oktavy a vyssich bitu frekvence db 0, 0 ; zarazka
4. První demonstrační příklad: upravené přehrání komorního A
A takto vypadá dnešní první demonstrační příklad, který obsahuje upravenou podobu tabulky s hodnotami registrů, které jsou pojmenovány:
; Prehrani zakladniho tonu na kartach s cipem OPL2. ; Pojmenovani registru OPL2. ; ; ; preklad pomoci: ; nasm -f bin -o sound_opl2_table.com sound_opl2_table_2.asm ; ; nebo pouze: ; nasm -o sound_opl2_table.com sound_opl2_table_2.asm ;----------------------------------------------------------------------------- ; registry karet s cipem OPL2 OPL_ADDRESS equ 0x388 OPL_DATA equ 0x389 ; 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 ; 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 ;----------------------------------------------------------------------------- ; ukonceni procesu a navrat do DOSu %macro exit 0 ret %endmacro ; vyprazdneni bufferu klavesnice a cekani na klavesu %macro wait_key 0 xor ax, ax int 0x16 %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 wait_key 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, 0x10 ; uroven vystupu 40 dB db CHANNEL_1_OPERATOR_1 + OPL_ATTACK_DECAY, 0xF0 ; modulator: rychly nastup zvuku + pomale doznivani db CHANNEL_1_OPERATOR_1 + OPL_SUSTAIN_RELEASE, 0x77 ; urovne sustain a release pro modulator db CHANNEL_1_OPERATOR_1 + OPL_FREQUENCY_LOW, 0x41 ; frekvence zvuku (komorni A = 440 Hz) 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 + OPL_KEY_ON, 0x32 ; zapnuti/povoleni zvuku + nastaveni oktavy a vyssich bitu frekvence 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 ; cekani priblizne 3.3 mikrosekundy mov cl, 6 .delay1: in al, dx loop .delay1 mov al, ah ; zapis hodnoty do vybraneho registru mov dx, OPL_DATA out dx, al ; cekani priblizne 23 mikrosekund mov cl, 35 .delay2: in al, dx loop .delay2 ret
5. Problematika bitů KEY ON
Zvuky, které jsou přehrávané jednotlivými kanály čipu OPL2, nejsou obecně tvořeny čistě periodickým signálem. Je tomu tak především z toho důvodu, že na generovaný primární signál (sinusovka, poloviční sinusovka atd.) je aplikována obálka ADSR, o níž se ještě zmíníme dále. Ovšem uplatnit se může i zpětná vazba (feedback), která je taktéž pro každý operátor konfigurovatelná. Pokud tedy například budeme chtít přehrát zvuk, jehož první a/nebo druhý operátor bude mít nastavenou netriviální obálku (triviální obálkou je konstantní hodnota), bude nutné nějakým způsobem specifikovat začátek přehrávání a po požadované době i ukončení fáze sustain:
Obrázek 1: Obálka ovlivňující signál z libovolného operátoru.
Jak je z tohoto obrázku patrné, je celé řízení generování signálu s obálkou řízeno pomocí bitu KEY ON. Tento bit lze nezávisle nastavit pro každý kanál zvlášť, k tomuto účelu slouží vždy jeden bit registru B0 až B8. Pojďme si tedy ukázat způsob nastavení tohoto bitu přímo přes klávesnici IBM PC.
6. Klávesnice IBM PC, čtení scan kódů kláves
Bit KEY ON budeme nastavovat v čase, kdy je stisknut mezerník. IBM PC neumožňuje provádět přímý test, zda je nějaká klávesa stisknuta, ale musíme korektně zareagovat na její stisk (změnu stavu) a poté uvolnění (opět změna stavu). Jak to provést? Využijeme faktu, že takzvané scan kódy kláves je možné přečíst z portu 60H, ovšem za předpokladu, že sedmý bit portu 61H je nastavený na jedničku. Již v článku o PC Speakeru jsme se dozvěděli, že tyto porty ovládají čip 8255 (PPI); konkrétně 60H odpovídá PORTU A tohoto čipu a 61H portu B čipu 8255 (jedná se o HW porty, zatímco 60H/61H je pouze koncept generování adres pro I/O obvody). Po stisku klávesy lze přečíst její přímý scan kód, po uvolnění klávesy naopak kód zvýšený o 80H (tedy s nastaveným sedmým bitem).
Obrázek 2: Scan kódy kláves IBM PC. Povšimněte si kódu klávesy ESC a SPACE, které později využijeme. Zdroj: Sysman (stále užitečný, i po těch letech).
7. Realizace aktivního čekání na stisk klávesy
Podívejme se nyní na přímé čtení scan kódů stisknutých kláves. Nejprve si nadefinujeme adresy portů 60h a 61h, což je v assembleru velmi snadné:
; registry PPI PPI_PORT_A equ 0x60 PPI_PORT_B equ 0x61
Následně si nadefinujeme kódy kláves, jejichž stisk budeme testovat. K tomu je přidána definice konstanty, která je ke kódu klávesy přičtena ve chvíli, kdy je klávesa puštěna (KEY_RELEASE):
; kody klaves KEY_ESC equ 0x01 KEY_SPACE equ 0x39 KEY_RELEASE equ 0x80
Před vlastním čtením scan kódů kláves přenastavíme režim portu A obvodu 8255. Budeme totiž chtít, aby se na tomto portu objevovaly právě scan kódy a nikoli jiné informace:
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
Nyní se již konečně můžeme pokusit o přečtení scan kódu stisknuté/puštěné klávesy s testem, zda se jedná o klávesu, jejíž stav nás zajímá:
in al, PPI_PORT_A ; cteni stisknute klavesy cmp al, KEY_ESC ; test stisknute klavesy jeq esc_stisknuta ; pokud je naše klávesa stisknuta, skok
8. Poznámka na okraj: rozeskok podle kódu stisknuté klávesy
V assembleru lze snadno reprezentovat tabulku rozeskoků, přesněji řečeno tabulku s adresami podprogramů, které se mají zavolat na základě stisknuté klávesy. Pokusím se uvést praktický příklad získaný z textového editoru e.com, což je plnohodnotný DOSový editor, jehož celková velikost je jen 6kB a využívá různé assemblerovské triky.
V tomto editoru jsou definovány podprogramy pro přesun kurzoru doleva, pro skok na další stranu atd. atd. Aktuální funkce těchto podprogramů nás nezajímá; důležitá je pouze instrukce RET na jejich konci:
Left: ... ... ... ret PageDown: ... ... ... ret
Srdcem tohoto textového editoru je tabulka se šestnáctibitovými adresami těchto podprogramů, která je vhodně uspořádána podle kódů kláves (CTRL+A má vyvolat subrutinu WordLeft atd.):
;Jump tables: ^ = Ctrl ctrlTable dw na ;Undefined dw WordLeft ;^A dw na ;^B dw PageDown ;^C dw Right ;^D dw Up ;^E dw WordRight ;^F dw na ;^G or BEL dw BackSpace ;^H or BS dw Tab ;^I or HT dw na ;^J or LF dw na ;^K or VT dw na ;^L or FF dw CRet ;^M or CR dw na ;^N or SO dw na ;^O or SI dw na ;^P dw na ;^Q or DC1 dw PageUp ;^R or DC2 dw Left ;^S or DC3 dw DeleteWordR ;^T or DC4 dw na ;^U dw na ;^V dw na ;^W dw Down ;^X or CAN dw DeleteLine ;^Y dw na ;^Z dw DeleteWordL ;^[ dw DeleteToEOL ;^\ dw DeleteWordR ;^] dw UndeleteLine ;^^ dw DeleteLine ;^-
Nyní přečteme kód klávesy a zjistíme, jestli byla stlačena CTRL (kód již bude upravený tak, že Ctrl+A vrátí nulu atd.):
IsCtrl: mov si, OFFSET ctrlTable ;Jump to routine through table sub ah, ah jmp DoTableJump
Posledním krokem je vlastní zavolání subrutiny. Hodnotu v AX vynásobíme dvěma (jedná se o offset adresy), přičteme offset k počáteční adrese tabulky a nakonec provedeme nepřímý skok (který je vlastně základem celého triku):
DoTableJump: shl ax, 1 add si, ax call [WORD si] jmp NextKey
9. Druhý demonstrační příklad – aktivní čekání na stisk klávesy ESC
V dnešním druhém demonstračním příkladu je ukázáno, jakým způsobem je možné realizovat čekání na stisk vybrané klávesy, v tomto případě konkrétně klávesy ESC. Po stisku klávesy je program bez dalších operací ihned ukončen (ale sami si můžete doplnit zobrazení zprávy na začátku i na konci – příslušné makro je k dispozici):
; Zaklad prace s klavesnici ; ; ; preklad pomoci: ; nasm -f bin -o keyboard_basic.com keyboard_basic.asm ; ; nebo pouze: ; nasm -o keyboard_basic.com keyboard_basic.asm ;----------------------------------------------------------------------------- BITS 16 ; 16bitovy vystup pro DOS CPU 8086 ; specifikace pouziteho instrukcniho souboru ;----------------------------------------------------------------------------- ; 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 ;----------------------------------------------------------------------------- ; ukonceni procesu a navrat do DOSu %macro exit 0 ret %endmacro ; tisk retezce na obrazovku %macro print 1 mov dx, %1 mov ah, 9 int 0x21 %endmacro ;----------------------------------------------------------------------------- org 0x100 ; zacatek kodu pro programy typu COM (vzdy se zacina na 256) start: 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_ESC ; test stisknute klavesy jne .opak ; neni stisknuta? -> zkusme znovu exit
10. Ovládání bitu KEY ON z klávesnice
Nyní již máme k dispozici všechny informace nutné k tomu, abychom mohli bit KEY ON (pro první kanál) ovládat přímo z klávesnice, například mezerníkem. Pokud bude klávesa stisknuta, bit KEY ON nastavíme, v případě, že bude puštěna, naopak tento bit vynulujeme. Do registrů OPL2 je možný jen zápis, takže budeme muset přímo zapisovat nových osm bitů příslušného registru OPL2, což je konkrétně registr, který jsme pojmenovali OPL_KEY_ON:
.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
Nakonec ještě přidáme test na stisk klávesy ESC, která program ukončí:
.next_test_2: cmp al, KEY_ESC ; test stisknute klavesy ESC jne .opak ; neni stisknuta? -> zkusme znovu
11. Třetí demonstrační příklad: přímé ovládání bitu KEY ON mezerníkem
V dnešním třetím demonstračním příkladu je ukázán způsob ovládání přehrávání zvuku z prvního kanálu přes mezerník. Po stisku mezerníku se nastaví bit KEY ON pro první kanál, po puštění klávesy se naopak tento bit vynuluje:
; Prehrani zakladniho tonu na kartach s cipem OPL2. ; Pojmenovani registru OPL2. ; Ovladani KEY ON mezernikem ; Ukonceni aplikace stiskem ESC ; ; ; preklad pomoci: ; nasm -f bin -o sound_key_on.com sound_key_on.asm ; ; nebo pouze: ; nasm -o sound_key_on.com sound_key_on.asm ;----------------------------------------------------------------------------- ; registry karet s cipem OPL2 OPL_ADDRESS equ 0x388 OPL_DATA equ 0x389 ; 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 ; 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 ;----------------------------------------------------------------------------- ; 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_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, 0x10 ; uroven vystupu 40 dB db CHANNEL_1_OPERATOR_1 + OPL_ATTACK_DECAY, 0xF0 ; modulator: rychly nastup zvuku + pomale doznivani db CHANNEL_1_OPERATOR_1 + OPL_SUSTAIN_RELEASE, 0x77 ; urovne sustain a release pro modulator db CHANNEL_1_OPERATOR_1 + OPL_FREQUENCY_LOW, 0x41 ; frekvence zvuku (komorni A = 440 Hz) 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 + 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 ; AL - registr ; AH - hodnota mov dx, OPL_ADDRESS ; vyber registru pro modifikaci out dx, al ; cekani priblizne 3.3 mikrosekundy mov cl, 6 .delay1: in al, dx loop .delay1 mov al, ah ; zapis hodnoty do vybraneho registru mov dx, OPL_DATA out dx, al ; cekani priblizne 23 mikrosekund mov cl, 35 .delay2: in al, dx loop .delay2 ret
12. Nastavení obálky pro tón přehrávaný prvním kanálem
Nyní, když již umíme ovládat přehrávání tónu ve vybraném kanálu s využitím bitu KEY ON, se můžeme pokusit o změnu tvaru obálky. Nejprve prodloužíme dobu nástupu (attack) a doznívání (sustain). Připomeňme si, že se v obou případech jedná o čtyřbitové hodnoty, kde hodnota F znamená nejkratší náběh/doběh, hodnota 1 naopak nejdelší čas:
7 6 5 4 3 2 1 0 +-----+-----+-----+-----+-----+-----+-----+-----+ | Attack | Decay | | Rate | Rate | +-----+-----+-----+-----+-----+-----+-----+-----+
Nastavením nuly se příslušný čas vlastně stane nekonečným. Nastavme tedy časy zhruba v polovině nejdelšího intervalu:
db CHANNEL_1_OPERATOR_1 + OPL_ATTACK_DECAY, 0x44 ; modulator: pomaly nastup zvuku + pomale doznivani
Dále nastavíme časový údaj release rate (pokles po vynulování bitu KEY ON) a úroveň sustain. V tomto případě se ovšem již nejedná o časový údaj, ale o relativní amplitudu:
7 6 5 4 3 2 1 0 +-----+-----+-----+-----+-----+-----+-----+-----+ | Sustain Level | Release | | 24 12 6 3 | Rate | +-----+-----+-----+-----+-----+-----+-----+-----+
Nastavení bude vypadat takto:
db CHANNEL_1_OPERATOR_1 + OPL_SUSTAIN_RELEASE, 0x7f ; urovne sustain a release pro modulator
Tytéž operace provedeme i pro druhý operátor v prvním kanálu:
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
Po těchto úpravách bude možné mezerníkem zahájit sekvenci attack+decay+sustain. Držením mezerníku se řídí doba fáze sustain a po uvolnění mezerníku se přejde do fáze release následované nulovou amplitudou signálu.
13. Čtvrtý demonstrační příklad: přehrání tónu s modifikovanými obálkami ADSR
Podívejme se na úplný zdrojový kód dnešního čtvrtého příkladu, v němž po stisku mezerníku rozezní signál ovlivněný obálkami ADSR (jedna obálka pro modulátor, druhá pro nosnou):
; Prehrani zakladniho tonu na kartach s cipem OPL2. ; Pojmenovani registru OPL2. ; Ovladani KEY ON mezernikem ; Ukonceni aplikace stiskem ESC ; ; ; preklad pomoci: ; nasm -f bin -o sound_adsr.com sound_adsr.asm ; ; nebo pouze: ; nasm -o sound_adsr.com sound_adsr.asm ;----------------------------------------------------------------------------- ; registry karet s cipem OPL2 OPL_ADDRESS equ 0x388 OPL_DATA equ 0x389 ; 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 ; 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 ;----------------------------------------------------------------------------- ; 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_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, 0x10 ; uroven vystupu 40 dB db CHANNEL_1_OPERATOR_1 + OPL_ATTACK_DECAY, 0x44 ; 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_1 + OPL_FREQUENCY_LOW, 0x41 ; frekvence zvuku (komorni A = 440 Hz) 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 + 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 ; AL - registr ; AH - hodnota mov dx, OPL_ADDRESS ; vyber registru pro modifikaci out dx, al ; cekani priblizne 3.3 mikrosekundy mov cl, 6 .delay1: in al, dx loop .delay1 mov al, ah ; zapis hodnoty do vybraneho registru mov dx, OPL_DATA out dx, al ; cekani priblizne 23 mikrosekund mov cl, 35 .delay2: in al, dx loop .delay2 ret
14. Řízení změny frekvence výstupního tónu numerickými klávesami
K přímému ovládání zvuků generovaných čipem OPL2 máme k dispozici celou klávesnici IBM PC (která je ovšem odlišná od novější AT klávesnice – má totiž jen 83, resp. 84 kláves; k této problematice se ještě vrátíme). Pokusme se tedy upravit náš program takovým způsobem, aby bylo možné přes numerické klávesy ovládat úroveň signálu generovaného prvním operátorem. A tato úroveň vlastně ovlivňuje frekvenci výsledného tónu. Aby byla situace ještě zajímavější, je modifikace druhého operátoru operátorem prvním poměrně velká a obálka má nastaveny dlouhé časy. Tím pádem bude výsledek po zvukové stránce mnohem komplikovanější.
Do programu nejdříve přidáme kódy kláves 1 až 0, a to právě v tomto pořadí – nejde totiž o ASCII ale o scan kódy:
; kody klaves KEY_ESC equ 0x01 KEY_SPACE equ 0x39 KEY_RELEASE equ 0x80 KEY_1 equ 0x02 KEY_0 equ KEY_1 + 9
Dále můžeme po přečtení scan kódu klávesy zjistit, jestli je stlačena numerická klávesa, s využitím kombinace instrukcí CMP+JB (jump if below) a CMP+JA (jump if above). Poté již nastavíme příslušnou úroveň do rozsahu 2 až 12. Využijeme totiž toho, že KEY1 má právě hodnotu 2, takže nemusíme provádět odečet této konstanty od obsahu registru AL:
cmp al, KEY_1 ; test na numericke klavesy jb .next_test_3 ; hodnota "pod" kodem klavesy 1 cmp al, KEY_0 ja .next_test_3 ; hodnota "nad" kodem klavesy 0 mov bl, al ; makro prepisue AL -> nemuzeme ho primo pouzit write_opl_register CHANNEL_1_OPERATOR_1 + OPL_LEVEL, bl .next_test_3:
15. Pátý demonstrační příklad: řízení frekvence modulátoru při přehrávání
Nyní se podívejme, jak bude vypadat výsledný program po výše popsané úpravě:
; Prehrani zakladniho tonu na kartach s cipem OPL2. ; Pojmenovani registru OPL2. ; Ovladani KEY ON mezernikem ; Frekvence modulatoru rizena klavesami 1 az 0 ; Ukonceni aplikace stiskem ESC ; ; ; preklad pomoci: ; nasm -f bin -o sound_modulation.com sound_modulation.asm ; ; nebo pouze: ; nasm -o sound_modulation.com sound_modulation.asm ;----------------------------------------------------------------------------- ; registry karet s cipem OPL2 OPL_ADDRESS equ 0x388 OPL_DATA equ 0x389 ; 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 ; 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_0 equ KEY_1 + 9 ;----------------------------------------------------------------------------- ; 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_0 ja .next_test_3 ; hodnota "nad" kodem klavesy 0 mov bl, al ; makro prepisue AL -> nemuzeme ho primo pouzit write_opl_register CHANNEL_1_OPERATOR_1 + OPL_LEVEL, bl .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, 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_1 + OPL_FREQUENCY_LOW, 0x41 ; frekvence zvuku (komorni A = 440 Hz) 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 + 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 ; AL - registr ; AH - hodnota mov dx, OPL_ADDRESS ; vyber registru pro modifikaci out dx, al ; cekani priblizne 3.3 mikrosekundy mov cl, 6 .delay1: in al, dx loop .delay1 mov al, ah ; zapis hodnoty do vybraneho registru mov dx, OPL_DATA out dx, al ; cekani priblizne 23 mikrosekund mov cl, 35 .delay2: in al, dx loop .delay2 ret
16. Výsledné zvuky produkované demonstračními příklady
Zvuky a tóny, které jsou generovány demonstračními příklady popsanými v předchozích kapitolách, byly uloženy do souborů WAVe (bez komprimace), takže si je můžete snadno přehrát i bez nutnosti překladu a spouštění těchto příkladů na reálném PC či v emulátoru. Redakční systém Roota ovšem neumožňuje přímé vkládání značky pro přehrání multimediálních dat, takže je nutné si soubory se zvuky stáhnout přes kontextové menu příkazem Save link as… a poté spustit nějakým (prakticky naprosto libovolným) multimediálním přehrávačem:
- OPL2–1 zvuk komorního A přehraný prvním demonstračním příkladem (nelze nijak ovládat).
- OPL2–2 zvuk komorního A řízený mezerníkem. Na konci je slyšet dozvuk tvořený obálkou.
- OPL2–3 zvuk s definovanou obálkou, který má jasně slyšitelný začátek, pokles, střední část (libovolně dlouhou dobu) a doběh
- OPL2–4 zde se postupně mění síla modulátoru; nejvíce „zkreslený“ zvuk (a tedy i nejvíce zajímavý) je slyšet na konci záznamu
17. Banky nástrojů pro OPL2
Vraťme se ještě jednou k tabulce registrů čipu OPL2. Vynecháme přitom registry, které se týkají časovače nebo globální konfigurace. Zbudou nám ty registry, které je nutné nastavit pro zvolený kanál tak, aby se vyprodukoval kýžený zvuk:
Registr/registry | Registrů na kanál | Oficiální jméno |
---|---|---|
20..35 | 2 | Amp Mod / Vibrato / EG type / Key Scaling / Multiple |
40..55 | 2 | Key scaling level / Operator output level |
60..75 | 2 | Attack Rate / Decay Rate |
80..95 | 2 | Sustain Level / Release Rate |
A0..A8 | 1 | Frequency (low 8 bits) |
B0..B8 | 1 | Key On / Octave / Frequency (high 2 bits) |
C0..C8 | 1 | Feedback strength / Connection type |
E0..F5 | 2 | Wave Select |
Celkem | 13 |
OPL2 dokáže napodobit prakticky jakýkoli nástroj a samozřejmě dokáže vyprodukovat i další zvuky („laser“, vrtulník atd.). Pro přehrání noty určitým nástroje tedy vlastně potřebujeme nastavit oněch 13 hodnot a poté bitem KEY ON řídit přehrávání. Ovšem ve skutečnosti se některé registry týkají přehrávané noty (ta se mění často) a jen část registrů mění charakteristické zvuky nástroje. A právě nastavení registrů, které ovlivňují charakteristické zvuky nástroje, se ukládá do takzvaných bank nástrojů. Jedná se o soubory obsahující hodnoty těchto registrů a postupně vzniklo hned několik (pseudo)standardů v této oblasti.
Obrázek 3: Interaktivní editace nástroje (zde konkrétně elektrické kytary).
Příkladem banky nástrojů může být například formát používaný společností Apogee, z jehož popisu je jasně patrná vazba na OPL. Poněkud složitější je formát navržený přímo společností AdLib a na půli cesty stojí formát IBK. Setkáme se i s formátem SBI, z jehož popisu je opět zřejmé přímé propojení s OPL. Důsledkem této rozstříštěnosti standardů je, že zejména moderní editory nástrojů pro OPL2 (nebo i OPL3) většinou podporují více souborových formátů, a to jak pro import, tak i pro export.
18. Trackery pro OPL2
Ve chvíli, kdy existují banky nástrojů, již můžeme přistoupit k dalšímu typu SW. Jedná se o takzvané trackery umožňující tvorbu hudby. S tímto důležitým a stále užitečným konceptem se seznámíme v navazujícím článku.
Obrázek 4: Tracker, který přímo umožňuje tvorbu hudby pro OPL2 (a mnoho dalších činností).
Obrázek 5: Tracker, který přímo umožňuje tvorbu hudby pro OPL2 (a mnoho dalších činností).
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 |
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