Obsah
1. Programování zvukových karet s čipem OPL3 nebo s dvojicí čipů OPL2
2. Sound Blaster Pro 1 s konfigurací DualOPL2
3. Přehrání tónu ve vybraném reproduktoru
4. Úplný zdrojový kód dnešního prvního demonstračního příkladu
5. Vícekanálový výstup z OPL2 (až devítihlasová polyfonie)
6. Nastavení not pro osm kanálů
7. Ovládání přehrání not klávesnicí
8. Úplný zdrojový kód dnešního druhého demonstračního příkladu
9. Vylepšení ovládání čipů OPL přes tabulku kláves+akcí: plnohodnotné „klávesy“ v 284 bajtech
10. Úplný zdrojový kód dnešního třetího demonstračního příkladu
11. Čip OPL3 z pohledu programátora
14. Demonstrační příklad: programová změna zvukového výstupu do levého, pravého i obou reproduktorů
15. Nastavení čipu OPL3 do režimu NEkompatibilního s OPL2
16. Demonstrační příklad: funkční programový výběr zvukového výstupu
17. Režim využívající 18 zvukových kanálů
18. Demonstrační příklad: využití většiny zvukových kanálů čipu OPL3
19. Repositář s demonstračními příklady
1. Programování zvukových karet s čipem OPL3 nebo s dvojicí čipů OPL2
V předchozím článku jsme si popsali postupný vývoj zvukových karet určených pro IBM PC, které obsahovaly čip OPL2 nebo OPL3. Připomeňme si ve stručnosti, že čipy OPL2, popř. OPL3 se ve světě PC využívaly poměrně dlouho – karty s těmito čipy se vyráběly od roku 1987 minimálně do roku 1996, ovšem různé klony SoundBlasterů byly vyráběny i po roce 1996. Jen zvolna byla FM syntéza nahrazována zvukovými kartami, které pro generování hudby využívaly wave table syntézu.
Dnešní článek bude zaměřen na vlastnosti čipů OPL2 a OPL3 z pohledu programátora. Ukážeme si, jak se ovládala dvojice čipů OPL2 (což bylo meziobdobí mezi kartami s jedním OPL2 na jedné straně a jedním „stereo“ OPL3 na straně druhé), jak lze na OPL2 i OPL3 využít polyfonii a taktéž ovládání levého a pravého reproduktoru čipem OPL3, čímž se pro jednotlivé kanály realizuje velmi triviální „stereo“ (ovšem bez možnosti plynulého panningu).
2. Sound Blaster Pro 1 s konfigurací DualOPL2
Existovaly celkem čtyři různé varianty využití čipů OPL:
- Jediný čip OPL2 v první a druhé generaci zvukových karet
- Dva čipy OPL2 pro realizaci určité formy stereo výstupu (bez panningu)
- Čip OPL3, který opět do určité míry umožňuje stereo výstup
- (Speciality typu dvojice OPL3 se čtyřmi výstupními kanály atd.)
Programování jediného čipu OPL2 jsme si již ukázali (a dnes se k němu ještě vrátíme), ovšem zajímavý je druhý způsob využívající dvojici čipů OPL2. Tuto konfiguraci měl Sound Blater Pro (bez dvojky) z roku 1991. Pro FM syntézu se v této kartě využívala dvojice čipů OPL2, přičemž každý čip byl zapojen do jednoho zvukového kanálu. Pokud byl požadovaný monofonní výstup (například z důvodu zpětné kompatibility), musely se buď oba čipy programovat se stejnými hodnotami řídicích registrů, nebo bylo možné použít adresu společnou pro oba čipy (adresní logika na kartě sama zařídila, že se hodnoty registrů zapsaly na oba čipy současně). Nutno dodat, že tento způsob zapojení, který se někdy označuje termínem DualOPL2, je poměrně unikátní právě pro Sound Blaster Pro a vlastně jen málo her dokázalo možnosti dvou OPL2 využít.
Pokud si budete chtít vlastnosti Sound Blasteru Pro 1.0 s Dual OPL2 otestovat v DOSBoxu, je nutné změnit jeho konfiguraci následovně:
sbtype = sbpro1 sbbase = 220 irq = 7 dma = 1 hdma = 5 sbmixer = false sbwarmup = 100 oplmode = dualopl2 sb_filter = off sb_filter_always_on = false opl_filter = on cms_filter = on
3. Přehrání tónu ve vybraném reproduktoru
Jak tedy vypadá programové přehrání tónu v levém nebo pravém reproduktoru v případě, že máme kartu v konfiguraci DualOPL2? Z hlediska programátora je to ve skutečnosti poměrně snadno řešitelný problém, protože řídicí registry jednoho čipu OPL2 (levý reproduktor) jsou mapovány na I/O porty 0×220 a 0×221 (výběr registru na prvním portu, zápis nové hodnoty na portu druhém). A pro druhý OPL2 (ten ovládá pravý reproduktor) se jedná o I/O porty 0×222 a 0×223. Pokud se zápis provede přes „AdLibovské“ porty 0×388 a 0×389, dojde k zápisu do obou OPL2.
Připravíme si tedy pomocné konstanty. První dvě budou obsahovat adresy portů pro „levý“ OPL:
; registry karet s cipem OPL2 OPL_ADDRESS equ 0x220 OPL_DATA equ 0x221
Následují definice offsetů, které použijeme pro výpočet skutečně použitých portů při zápisu („pravý“ OPL má adresy zvýšené o dvojku):
; vyber levelo a praveho reproduktoru LEFT_SPEAKER equ 0 RIGHT_SPEAKER equ 2 ; musi byt 2!!!
Zápis hodnot řídicích registrů z tabulky do levého či pravého OPL nepatrně upravíme, a to tak, že před vlastním zápisem nastavíme hodnotu registru BX na 0 nebo 2 (což je kýžený offset od adresy 0×220, resp. 0×221):
mov si, tones ; zacatek tabulky mov bx, RIGHT_SPEAKER call write_table_to_opl2 ; zapis obsahu tabulky do OPL2
Subrutina pro zápis do vybraného registru OPL tedy bude vypadat následovně (povšimněte si zvýšení adresy o BX):
perform_write_to_opl_register: ; zapis do vybraneho registru OPL2 ; AL - registr ; AH - hodnota ; BX - výběr levého či pravého OPL (0 nebo 2) mov dx, OPL_ADDRESS ; vyber registru pro modifikaci add dx, bx 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 add dx, bx out dx, al ; cekani priblizne 23 mikrosekund mov cl, 35 .delay2: in al, dx loop .delay2 ret
db CHANNEL_1 + OPL_FEEDBACK, 0x00 ; libovolny zapis zpusobi, ze kazdy OPL2 ovlada svuj kanal
4. Úplný zdrojový kód dnešního prvního demonstračního příkladu
V dnešním prvním demonstračním příkladu je ukázáno ovládání dvojice čipů OPL2 tak, jak bylo popsáno v předchozích kapitolách. Změnou zvýrazněného řádku je možné určit, do jakého reproduktoru bude zvuk poslán, tj. jaký OPL2 čip bude použit:
mov si, tones ; zacatek tabulky mov bx, LEFT_SPEAKER call write_table_to_opl2 ; zapis obsahu tabulky do OPL2
nebo:
mov si, tones ; zacatek tabulky mov bx, RIGHT_SPEAKER call write_table_to_opl2 ; zapis obsahu tabulky do OPL2
Zdrojový kód tohoto příkladu vypadá následovně:
; Prehrani zakladniho tonu na kartach s dvojici cipu OPL2. ; Pojmenovani registru OPL2. ; ; ; preklad pomoci: ; nasm -f bin -o sound_opl2_table.com sound_dual_opl2.asm ; ; nebo pouze: ; nasm -o sound_opl2_table.com sound_dual_opl2.asm ;----------------------------------------------------------------------------- BITS 16 ; 16bitovy vystup pro DOS CPU 8086 ; specifikace pouziteho instrukcniho souboru ;----------------------------------------------------------------------------- ; registry karet s cipem OPL2 OPL_ADDRESS equ 0x220 OPL_DATA equ 0x221 ; vyber levelo a praveho reproduktoru LEFT_SPEAKER equ 0 RIGHT_SPEAKER equ 2 ; musi byt 2!!! ; 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, tones ; zacatek tabulky mov bx, RIGHT_SPEAKER 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 tones: ; 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_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_FREQUENCY_LOW, 0x41 ; frekvence zvuku (komorni A = 440 Hz) db CHANNEL_1 + OPL_FEEDBACK, 0x00 ; libovolny zapis zpusobi, ze kazdy OPL2 ovlada svuj kanal 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 add dx, bx 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 add dx, bx out dx, al ; cekani priblizne 23 mikrosekund mov cl, 35 .delay2: in al, dx loop .delay2 ret
5. Vícekanálový výstup z OPL2 (až devítihlasová polyfonie)
Vraťme se ještě na chvíli k původnímu „jednoduchému“ čipu OPL2. Připomeňme si, že tyto čipy podporovaly celkem devět zvukových kanálů, které jsou na sobě nezávislé – každý kanál je možné individuálně ovládat a nastavovat jeho parametry. A každý kanál je tvořen dvojicí operátorů, které mohou být zapojeny různým způsobem – paralelně (AM modulace) či sériově (FM, resp. fázová modulace). Výsledkem je, že čip OPL2 dokáže přehrávat devět na sobě nezávislých tónů v případě, že není nastaven perkusní režim (což je trošku magie, která si vyžádá samostatný text). Každý kanál má svoji sadu řídicích registrů a vzhledem k tomu, že některé registry jsou určeny pro jednotlivé operátory, je těchto registrů poměrně velké množství.
Registry | Platné pro | Počet registrů | Oficiální jméno |
---|---|---|---|
20..35 | operátor | 18 | Amp Mod / Vibrato / EG type / Key Scaling / Multiple |
40..55 | operátor | 18 | Key scaling level / Operator output level |
60..75 | operátor | 18 | Attack Rate / Decay Rate |
80..95 | operátor | 18 | Sustain Level / Release Rate |
A0..A8 | kanál | 9 | Frequency (low 8 bits) |
B0..B8 | kanál | 9 | Key On / Octave / Frequency (high 2 bits) |
C0..C8 | kanál | 9 | Feedback strength / Connection type |
E0..F5 | kanál | 9 | Wave Select |
Popř. se na celý problém můžeme podívat ze strany: pro nastavení každého kanálu potřebujeme 12 registrů: 4×2 registry pro nastavení operátorů a 4×1 registr pro nastavení vlastnosti celého kanálu. Ovšem některé registry jsou zpočátku vynulovány a my je nebudeme muset měnit (například výběr tvaru signálu nebo způsob zapojení operátorů – ponecháme výchozí hodnoty).
6. Nastavení not pro osm kanálů
Již umíme naprogramovat nastavení registrů jediného kanálu. Připomeňme si, že k tomuto účelu používáme tabulku, která vypadá následovně:
tones: ; 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_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_FREQUENCY_LOW, 0x41 ; frekvence zvuku (komorni A = 440 Hz) db 0, 0 ; zarazka
Povšimněte si, že skutečně nenastavujeme všechny registry vypsané v předchozí kapitole, protože to není zcela nutné. Tuto tabulku můžeme triviálně rozšířit i pro další kanály, pouze nesmíme zapomenout na umístění zarážky za poslední hodnotou.
Rozšířená tabulka bude obsahovat pro každý kanál pouze výše uvedené registry (9 bajtů), přičemž registr OPL_KEY_ON budeme ovládat přímo z klávesnice, ze které si tak vytvoříme jednoduché „klávesy“ s osmi na sobě nezávislými notami. Jednotlivé kanály se budu lišit nastavenými frekvencemi (OPL_FREQUENCY_LOW + později OPL_KEY_ON), protože pro prvních osm kanálů postupně nastavíme noty C, D, E, F, G, A, H a vyšší C:
Hodnota pro zápis do registruNota | Frekvence | |
---|---|---|
C | 261.1 | 0×0ae |
D | 293.7 | 0×181 |
E | 329.6 | 0×1b0 |
F | 349.2 | 0×1ca |
G | 392.0 | 0×202 |
A | 440.0 | 0×241 |
H | 493.9 | 0×287 |
C | 523.3 | 0×2ae |
V tabulce s hodnotami registrů můžeme nastavit spodních osm bitů hodnoty z posledního sloupce tabulky, a to pro osm kanálů (devátý není použit):
db CHANNEL_1 + OPL_FREQUENCY_LOW, 0xae ; frekvence zvuku (C) db CHANNEL_2 + OPL_FREQUENCY_LOW, 0x81 ; frekvence zvuku (D) db CHANNEL_3 + OPL_FREQUENCY_LOW, 0xb0 ; frekvence zvuku (E) db CHANNEL_4 + OPL_FREQUENCY_LOW, 0xca ; frekvence zvuku (F) db CHANNEL_5 + OPL_FREQUENCY_LOW, 0x02 ; frekvence zvuku (G) db CHANNEL_6 + OPL_FREQUENCY_LOW, 0x41 ; frekvence zvuku (A) db CHANNEL_7 + OPL_FREQUENCY_LOW, 0x87 ; frekvence zvuku (B) db CHANNEL_8 + OPL_FREQUENCY_LOW, 0xae ; frekvence zvuku (C)
Horní bity hodnoty se nastavují v registrech OPL_KEY_ON, které budeme měnit při stisku či naopak uvolnění klávesy.
7. Ovládání přehrání not klávesnicí
Nyní musíme implementovat „klávesy“, konkrétně začátek přehrání či naopak zastavení přehrávání noty při stisku/uvolnění kláves 1 až 8 na PC klávesnici (samozřejmě si však můžete vybrat i odlišné klávesy). Nejprve přečteme kód stisknuté/uvolněné klávesy, což již známe z předchozího článku:
in al, PPI_PORT_A ; cteni stisknute klavesy
Dále si vytvoříme pomocná makra, která zareagují na stisk či uvolnění klávesy. Makrům se předá kód klávesy, index registru OPL, který se má změnit, a hodnota tohoto regsitru:
%macro on_key_press 3 cmp al, %1 ; test na stisk klavesy jne %%not_pressed ; neni stisknuta -> preskok write_opl_register %2, %3 ; povoleni KEY ON bitu jmp .opak %%not_pressed: %endmacro %macro on_key_release 3 cmp al, 0x80 + %1 ; test na uvolneni klavesy jne %%not_released ; neni uvolnena -> preskok write_opl_register %2, %3 ; zakaz KEY ON bitu jmp .opak %%not_released: %endmacro
Vlastní realizace „kláves“ vypadá sice vypadá velmi jednoduše (a taktéž ve skutečnosti jednoduchá je), ovšem výsledný strojový kód bude postupně narůstat kvůli expanzi maker:
on_key_press KEY_1, CHANNEL_1 + OPL_KEY_ON, 0b00101110 on_key_release KEY_1, CHANNEL_1 + OPL_KEY_ON, 0b00001110 on_key_press KEY_2, CHANNEL_2 + OPL_KEY_ON, 0b00110001 on_key_release KEY_2, CHANNEL_2 + OPL_KEY_ON, 0b00010001 on_key_press KEY_3, CHANNEL_3 + OPL_KEY_ON, 0b00110001 on_key_release KEY_3, CHANNEL_3 + OPL_KEY_ON, 0b00010001 on_key_press KEY_4, CHANNEL_4 + OPL_KEY_ON, 0b00110001 on_key_release KEY_4, CHANNEL_4 + OPL_KEY_ON, 0b00010001 on_key_press KEY_5, CHANNEL_5 + OPL_KEY_ON, 0b00110010 on_key_release KEY_5, CHANNEL_5 + OPL_KEY_ON, 0b00010010 on_key_press KEY_6, CHANNEL_6 + OPL_KEY_ON, 0b00110010 on_key_release KEY_6, CHANNEL_6 + OPL_KEY_ON, 0b00010010 on_key_press KEY_7, CHANNEL_7 + OPL_KEY_ON, 0b00110010 on_key_release KEY_7, CHANNEL_7 + OPL_KEY_ON, 0b00010010 on_key_press KEY_8, CHANNEL_8 + OPL_KEY_ON, 0b00110010 on_key_release KEY_8, CHANNEL_8 + OPL_KEY_ON, 0b00010010
8. Úplný zdrojový kód dnešního druhého demonstračního příkladu
Ukažme si nyní úplný zdrojový kód dnešního druhého demonstračního příkladu, který po svém spuštění reaguje na klávesy 1..8 a na základě kombinace stisku těchto kláves povoluje či zakazuje zvukové kanály 1..8 bitem KEY_ON. Jak bylo popsáno výše, je možné přehrát více not:
; Prehrani zakladniho tonu na kartach s cipem OPL2. ; Pojmenovani registru OPL2. ; ; ; preklad pomoci: ; nasm -f bin -o sound_opl2_table.com sound_opl2_multichannel.asm ; ; nebo pouze: ; nasm -o sound_opl2_table.com sound_opl2_multichannel.asm ;----------------------------------------------------------------------------- BITS 16 ; 16bitovy vystup pro DOS CPU 8086 ; specifikace pouziteho instrukcniho souboru ;----------------------------------------------------------------------------- ; 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_2 equ 0x03 KEY_3 equ 0x04 KEY_4 equ 0x05 KEY_5 equ 0x06 KEY_6 equ 0x07 KEY_7 equ 0x08 KEY_8 equ 0x09 ;----------------------------------------------------------------------------- ; 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 %macro on_key_press 3 cmp al, %1 ; test na stisk klavesy jne %%not_pressed ; neni stisknuta -> preskok write_opl_register %2, %3 ; povoleni KEY ON bitu jmp .opak %%not_pressed: %endmacro %macro on_key_release 3 cmp al, 0x80 + %1 ; test na uvolneni klavesy jne %%not_released ; neni uvolnena -> preskok write_opl_register %2, %3 ; zakaz KEY ON bitu jmp .opak %%not_released: %endmacro ;----------------------------------------------------------------------------- org 0x100 ; zacatek kodu pro programy typu COM (vzdy se zacina na 256) start: push cs pop ds ; DS==CS mov si, tones ; 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 on_key_press KEY_1, CHANNEL_1 + OPL_KEY_ON, 0b00101110 on_key_release KEY_1, CHANNEL_1 + OPL_KEY_ON, 0b00001110 on_key_press KEY_2, CHANNEL_2 + OPL_KEY_ON, 0b00110001 on_key_release KEY_2, CHANNEL_2 + OPL_KEY_ON, 0b00010001 on_key_press KEY_3, CHANNEL_3 + OPL_KEY_ON, 0b00110001 on_key_release KEY_3, CHANNEL_3 + OPL_KEY_ON, 0b00010001 on_key_press KEY_4, CHANNEL_4 + OPL_KEY_ON, 0b00110001 on_key_release KEY_4, CHANNEL_4 + OPL_KEY_ON, 0b00010001 on_key_press KEY_5, CHANNEL_5 + OPL_KEY_ON, 0b00110010 on_key_release KEY_5, CHANNEL_5 + OPL_KEY_ON, 0b00010010 on_key_press KEY_6, CHANNEL_6 + OPL_KEY_ON, 0b00110010 on_key_release KEY_6, CHANNEL_6 + OPL_KEY_ON, 0b00010010 on_key_press KEY_7, CHANNEL_7 + OPL_KEY_ON, 0b00110010 on_key_release KEY_7, CHANNEL_7 + OPL_KEY_ON, 0b00010010 on_key_press KEY_8, CHANNEL_8 + OPL_KEY_ON, 0b00110010 on_key_release KEY_8, CHANNEL_8 + OPL_KEY_ON, 0b00010010 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 tones: ; tabulka s tony pro osm kanalu 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, 0x55 ; 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_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_FREQUENCY_LOW, 0xae ; frekvence zvuku (C) db CHANNEL_2_OPERATOR_1 + OPL_AMP_VIBRATO_EG, 0x01 ; nastaveni modulatoru: nasobeni frekvence jednickou db CHANNEL_2_OPERATOR_1 + OPL_LEVEL, 0x10 ; uroven vystupu 40 dB db CHANNEL_2_OPERATOR_1 + OPL_ATTACK_DECAY, 0x55 ; modulator: rychly nastup zvuku + pomale doznivani db CHANNEL_2_OPERATOR_1 + OPL_SUSTAIN_RELEASE, 0x77 ; urovne sustain a release pro modulator db CHANNEL_2_OPERATOR_2 + OPL_AMP_VIBRATO_EG, 0x01 ; nastaveni nosne: nasobeni frekvence jednickou db CHANNEL_2_OPERATOR_2 + OPL_LEVEL, 0x00 ; nastaveni urovne vystupu nosne na 47 dB db CHANNEL_2_OPERATOR_2 + OPL_ATTACK_DECAY, 0xF0 ; nosna: rychly nastup + pomale doznivani db CHANNEL_2_OPERATOR_2 + OPL_SUSTAIN_RELEASE, 0x77 ; urovne sustain a release pro nosnou db CHANNEL_2 + OPL_FREQUENCY_LOW, 0x81 ; frekvence zvuku (D) db CHANNEL_3_OPERATOR_1 + OPL_AMP_VIBRATO_EG, 0x01 ; nastaveni modulatoru: nasobeni frekvence jednickou db CHANNEL_3_OPERATOR_1 + OPL_LEVEL, 0x10 ; uroven vystupu 40 dB db CHANNEL_3_OPERATOR_1 + OPL_ATTACK_DECAY, 0x55 ; modulator: rychly nastup zvuku + pomale doznivani db CHANNEL_3_OPERATOR_1 + OPL_SUSTAIN_RELEASE, 0x77 ; urovne sustain a release pro modulator db CHANNEL_3_OPERATOR_2 + OPL_AMP_VIBRATO_EG, 0x01 ; nastaveni nosne: nasobeni frekvence jednickou db CHANNEL_3_OPERATOR_2 + OPL_LEVEL, 0x00 ; nastaveni urovne vystupu nosne na 47 dB db CHANNEL_3_OPERATOR_2 + OPL_ATTACK_DECAY, 0xF0 ; nosna: rychly nastup + pomale doznivani db CHANNEL_3_OPERATOR_2 + OPL_SUSTAIN_RELEASE, 0x77 ; urovne sustain a release pro nosnou db CHANNEL_3 + OPL_FREQUENCY_LOW, 0xb0 ; frekvence zvuku (E) db CHANNEL_4_OPERATOR_1 + OPL_AMP_VIBRATO_EG, 0x01 ; nastaveni modulatoru: nasobeni frekvence jednickou db CHANNEL_4_OPERATOR_1 + OPL_LEVEL, 0x10 ; uroven vystupu 40 dB db CHANNEL_4_OPERATOR_1 + OPL_ATTACK_DECAY, 0x55 ; modulator: rychly nastup zvuku + pomale doznivani db CHANNEL_4_OPERATOR_1 + OPL_SUSTAIN_RELEASE, 0x77 ; urovne sustain a release pro modulator db CHANNEL_4_OPERATOR_2 + OPL_AMP_VIBRATO_EG, 0x01 ; nastaveni nosne: nasobeni frekvence jednickou db CHANNEL_4_OPERATOR_2 + OPL_LEVEL, 0x00 ; nastaveni urovne vystupu nosne na 47 dB db CHANNEL_4_OPERATOR_2 + OPL_ATTACK_DECAY, 0xF0 ; nosna: rychly nastup + pomale doznivani db CHANNEL_4_OPERATOR_2 + OPL_SUSTAIN_RELEASE, 0x77 ; urovne sustain a release pro nosnou db CHANNEL_4 + OPL_FREQUENCY_LOW, 0xca ; frekvence zvuku (F) db CHANNEL_5_OPERATOR_1 + OPL_AMP_VIBRATO_EG, 0x01 ; nastaveni modulatoru: nasobeni frekvence jednickou db CHANNEL_5_OPERATOR_1 + OPL_LEVEL, 0x10 ; uroven vystupu 40 dB db CHANNEL_5_OPERATOR_1 + OPL_ATTACK_DECAY, 0x55 ; modulator: rychly nastup zvuku + pomale doznivani db CHANNEL_5_OPERATOR_1 + OPL_SUSTAIN_RELEASE, 0x77 ; urovne sustain a release pro modulator db CHANNEL_5_OPERATOR_2 + OPL_AMP_VIBRATO_EG, 0x01 ; nastaveni nosne: nasobeni frekvence jednickou db CHANNEL_5_OPERATOR_2 + OPL_LEVEL, 0x00 ; nastaveni urovne vystupu nosne na 47 dB db CHANNEL_5_OPERATOR_2 + OPL_ATTACK_DECAY, 0xF0 ; nosna: rychly nastup + pomale doznivani db CHANNEL_5_OPERATOR_2 + OPL_SUSTAIN_RELEASE, 0x77 ; urovne sustain a release pro nosnou db CHANNEL_5 + OPL_FREQUENCY_LOW, 0x02 ; frekvence zvuku (G) db CHANNEL_6_OPERATOR_1 + OPL_AMP_VIBRATO_EG, 0x01 ; nastaveni modulatoru: nasobeni frekvence jednickou db CHANNEL_6_OPERATOR_1 + OPL_LEVEL, 0x10 ; uroven vystupu 40 dB db CHANNEL_6_OPERATOR_1 + OPL_ATTACK_DECAY, 0x55 ; modulator: rychly nastup zvuku + pomale doznivani db CHANNEL_6_OPERATOR_1 + OPL_SUSTAIN_RELEASE, 0x77 ; urovne sustain a release pro modulator db CHANNEL_6_OPERATOR_2 + OPL_AMP_VIBRATO_EG, 0x01 ; nastaveni nosne: nasobeni frekvence jednickou db CHANNEL_6_OPERATOR_2 + OPL_LEVEL, 0x00 ; nastaveni urovne vystupu nosne na 47 dB db CHANNEL_6_OPERATOR_2 + OPL_ATTACK_DECAY, 0xF0 ; nosna: rychly nastup + pomale doznivani db CHANNEL_6_OPERATOR_2 + OPL_SUSTAIN_RELEASE, 0x77 ; urovne sustain a release pro nosnou db CHANNEL_6 + OPL_FREQUENCY_LOW, 0x41 ; frekvence zvuku (A) db CHANNEL_7_OPERATOR_1 + OPL_AMP_VIBRATO_EG, 0x01 ; nastaveni modulatoru: nasobeni frekvence jednickou db CHANNEL_7_OPERATOR_1 + OPL_LEVEL, 0x10 ; uroven vystupu 40 dB db CHANNEL_7_OPERATOR_1 + OPL_ATTACK_DECAY, 0x55 ; modulator: rychly nastup zvuku + pomale doznivani db CHANNEL_7_OPERATOR_1 + OPL_SUSTAIN_RELEASE, 0x77 ; urovne sustain a release pro modulator db CHANNEL_7_OPERATOR_2 + OPL_AMP_VIBRATO_EG, 0x01 ; nastaveni nosne: nasobeni frekvence jednickou db CHANNEL_7_OPERATOR_2 + OPL_LEVEL, 0x00 ; nastaveni urovne vystupu nosne na 47 dB db CHANNEL_7_OPERATOR_2 + OPL_ATTACK_DECAY, 0xF0 ; nosna: rychly nastup + pomale doznivani db CHANNEL_7_OPERATOR_2 + OPL_SUSTAIN_RELEASE, 0x77 ; urovne sustain a release pro nosnou db CHANNEL_7 + OPL_FREQUENCY_LOW, 0x87 ; frekvence zvuku (B) db CHANNEL_8_OPERATOR_1 + OPL_AMP_VIBRATO_EG, 0x01 ; nastaveni modulatoru: nasobeni frekvence jednickou db CHANNEL_8_OPERATOR_1 + OPL_LEVEL, 0x10 ; uroven vystupu 40 dB db CHANNEL_8_OPERATOR_1 + OPL_ATTACK_DECAY, 0x55 ; modulator: rychly nastup zvuku + pomale doznivani db CHANNEL_8_OPERATOR_1 + OPL_SUSTAIN_RELEASE, 0x77 ; urovne sustain a release pro modulator db CHANNEL_8_OPERATOR_2 + OPL_AMP_VIBRATO_EG, 0x01 ; nastaveni nosne: nasobeni frekvence jednickou db CHANNEL_8_OPERATOR_2 + OPL_LEVEL, 0x00 ; nastaveni urovne vystupu nosne na 47 dB db CHANNEL_8_OPERATOR_2 + OPL_ATTACK_DECAY, 0xF0 ; nosna: rychly nastup + pomale doznivani db CHANNEL_8_OPERATOR_2 + OPL_SUSTAIN_RELEASE, 0x77 ; urovne sustain a release pro nosnou db CHANNEL_8 + OPL_FREQUENCY_LOW, 0xae ; frekvence zvuku (C) 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
9. Vylepšení ovládání čipů OPL přes tabulku kláves+akcí: plnohodnotné „klávesy“ v 284 bajtech
Předchozí demonstrační příklad je sice plně funkční, ale po překladu získáme program typu COM, který má velikost 422 bajtů. To je poměrně hodně (i když asi ne z dnešního pohledu). Pokusme se tedy nahradit volání maker spíše tabulkou, v níž bude zapsána jak událost, na kterou reagujeme (stisk/uvolnění klávesy), tak i potřebná změna OPL. Samozřejmě opět nesmíme zapomenout na „zarážku“ na konci tabulky:
key_actions: db KEY_1, CHANNEL_1 + OPL_KEY_ON, 0b00101110 db KEY_1+KEY_RELEASE, CHANNEL_1 + OPL_KEY_ON, 0b00001110 db KEY_2, CHANNEL_2 + OPL_KEY_ON, 0b00110001 db KEY_2+KEY_RELEASE, CHANNEL_2 + OPL_KEY_ON, 0b00010001 db KEY_3, CHANNEL_3 + OPL_KEY_ON, 0b00110001 db KEY_3+KEY_RELEASE, CHANNEL_3 + OPL_KEY_ON, 0b00010001 db KEY_4, CHANNEL_4 + OPL_KEY_ON, 0b00110001 db KEY_4+KEY_RELEASE, CHANNEL_4 + OPL_KEY_ON, 0b00010001 db KEY_5, CHANNEL_5 + OPL_KEY_ON, 0b00110010 db KEY_5+KEY_RELEASE, CHANNEL_5 + OPL_KEY_ON, 0b00010010 db KEY_6, CHANNEL_6 + OPL_KEY_ON, 0b00110010 db KEY_6+KEY_RELEASE, CHANNEL_6 + OPL_KEY_ON, 0b00010010 db KEY_7, CHANNEL_7 + OPL_KEY_ON, 0b00110010 db KEY_7+KEY_RELEASE, CHANNEL_7 + OPL_KEY_ON, 0b00010010 db KEY_8, CHANNEL_8 + OPL_KEY_ON, 0b00110010 db KEY_8+KEY_RELEASE, CHANNEL_8 + OPL_KEY_ON, 0b00010010 db 0, 0 ; zarazka
Postupné porovnání přečteného kódu klávesy a vyvolání příslušné akce lze realizovat následující programovou smyčkou (tu by navíc ještě bylo možné optimalizovat jinou alokací registrů):
.opak: in al, PPI_PORT_A ; cteni stisknute klavesy cmp al, KEY_ESC ; test na stisk ESC je .exit ; pokud stisknuta, konec programu mov ah, al ; kod klavesy do registru AH pro dalsi pouziti mov si, key_actions ; tabulka akci pri stisku ci uvolneni klavesy .next_key: lodsb ; nacist kod klavesy z tabulky or al, al ; test na nulu (zarazka) jz .opak ; nic jsme jiz nenasli -> cteni klavesy pres port cmp ah, al ; nasli jsme kod klavesy, ktery zname? jne .try_next_key lodsb ; adresa OPL registru mov ah, al lodsb ; hodnota OPL registru xchg ah, al ; vtipne jsme si prohodili parametry subrutiny write_opl_register call perform_write_to_opl_register jmp .next_key ; zkusit dalsi klavesu .try_next_key: add si, 2 ; preskocit adresu registru + jeho hodnotu jmp .next_key
Výsledkem jsou plnohodnotné „klávesy“ realizované programem o velikosti 284 bajtů, ve kterém je navíc možné individuálně měnit zvuk každého kanálu (noty).
10. Úplný zdrojový kód dnešního třetího demonstračního příkladu
Upravený a do určité míry optimalizovaný příklad s realizací „kláves“ na IBM PC bude vypadat následovně. Jak jsme si již řekli v předchozí kapitoly, bude výsledný program nejenom kratší, ale i poněkud přehlednější:
; Prehrani zakladniho tonu na kartach s cipem OPL2. ; Pojmenovani registru OPL2. ; ; ; preklad pomoci: ; nasm -f bin -o sound_opl2_table.com sound_opl2_multichannel.asm ; ; nebo pouze: ; nasm -o sound_opl2_table.com sound_opl2_multichannel.asm ;----------------------------------------------------------------------------- BITS 16 ; 16bitovy vystup pro DOS CPU 8086 ; specifikace pouziteho instrukcniho souboru ;----------------------------------------------------------------------------- ; 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_2 equ 0x03 KEY_3 equ 0x04 KEY_4 equ 0x05 KEY_5 equ 0x06 KEY_6 equ 0x07 KEY_7 equ 0x08 KEY_8 equ 0x09 ;----------------------------------------------------------------------------- ; 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, tones ; 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_ESC ; test na stisk ESC je .exit ; pokud stisknuta, konec programu mov ah, al ; kod klavesy do registru AH pro dalsi pouziti mov si, key_actions ; tabulka akci pri stisku ci uvolneni klavesy .next_key: lodsb ; nacist kod klavesy z tabulky or al, al ; test na nulu (zarazka) jz .opak ; nic jsme jiz nenasli -> cteni klavesy pres port cmp ah, al ; nasli jsme kod klavesy, ktery zname? jne .try_next_key lodsb ; adresa OPL registru mov ah, al lodsb ; hodnota OPL registru xchg ah, al ; vtipne jsme si prohodili parametry subrutiny write_opl_register call perform_write_to_opl_register jmp .next_key ; zkusit dalsi klavesu .try_next_key: add si, 2 ; preskocit adresu registru + jeho hodnotu jmp .next_key .exit: 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 key_actions: db KEY_1, CHANNEL_1 + OPL_KEY_ON, 0b00101110 db KEY_1+KEY_RELEASE, CHANNEL_1 + OPL_KEY_ON, 0b00001110 db KEY_2, CHANNEL_2 + OPL_KEY_ON, 0b00110001 db KEY_2+KEY_RELEASE, CHANNEL_2 + OPL_KEY_ON, 0b00010001 db KEY_3, CHANNEL_3 + OPL_KEY_ON, 0b00110001 db KEY_3+KEY_RELEASE, CHANNEL_3 + OPL_KEY_ON, 0b00010001 db KEY_4, CHANNEL_4 + OPL_KEY_ON, 0b00110001 db KEY_4+KEY_RELEASE, CHANNEL_4 + OPL_KEY_ON, 0b00010001 db KEY_5, CHANNEL_5 + OPL_KEY_ON, 0b00110010 db KEY_5+KEY_RELEASE, CHANNEL_5 + OPL_KEY_ON, 0b00010010 db KEY_6, CHANNEL_6 + OPL_KEY_ON, 0b00110010 db KEY_6+KEY_RELEASE, CHANNEL_6 + OPL_KEY_ON, 0b00010010 db KEY_7, CHANNEL_7 + OPL_KEY_ON, 0b00110010 db KEY_7+KEY_RELEASE, CHANNEL_7 + OPL_KEY_ON, 0b00010010 db KEY_8, CHANNEL_8 + OPL_KEY_ON, 0b00110010 db KEY_8+KEY_RELEASE, CHANNEL_8 + OPL_KEY_ON, 0b00010010 db 0, 0 ; zarazka tones: ; tabulka s tony pro osm kanalu 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, 0x55 ; 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_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_FREQUENCY_LOW, 0xae ; frekvence zvuku (C) db CHANNEL_2_OPERATOR_1 + OPL_AMP_VIBRATO_EG, 0x01 ; nastaveni modulatoru: nasobeni frekvence jednickou db CHANNEL_2_OPERATOR_1 + OPL_LEVEL, 0x10 ; uroven vystupu 40 dB db CHANNEL_2_OPERATOR_1 + OPL_ATTACK_DECAY, 0x55 ; modulator: rychly nastup zvuku + pomale doznivani db CHANNEL_2_OPERATOR_1 + OPL_SUSTAIN_RELEASE, 0x77 ; urovne sustain a release pro modulator db CHANNEL_2_OPERATOR_2 + OPL_AMP_VIBRATO_EG, 0x01 ; nastaveni nosne: nasobeni frekvence jednickou db CHANNEL_2_OPERATOR_2 + OPL_LEVEL, 0x00 ; nastaveni urovne vystupu nosne na 47 dB db CHANNEL_2_OPERATOR_2 + OPL_ATTACK_DECAY, 0xF0 ; nosna: rychly nastup + pomale doznivani db CHANNEL_2_OPERATOR_2 + OPL_SUSTAIN_RELEASE, 0x77 ; urovne sustain a release pro nosnou db CHANNEL_2 + OPL_FREQUENCY_LOW, 0x81 ; frekvence zvuku (D) db CHANNEL_3_OPERATOR_1 + OPL_AMP_VIBRATO_EG, 0x01 ; nastaveni modulatoru: nasobeni frekvence jednickou db CHANNEL_3_OPERATOR_1 + OPL_LEVEL, 0x10 ; uroven vystupu 40 dB db CHANNEL_3_OPERATOR_1 + OPL_ATTACK_DECAY, 0x55 ; modulator: rychly nastup zvuku + pomale doznivani db CHANNEL_3_OPERATOR_1 + OPL_SUSTAIN_RELEASE, 0x77 ; urovne sustain a release pro modulator db CHANNEL_3_OPERATOR_2 + OPL_AMP_VIBRATO_EG, 0x01 ; nastaveni nosne: nasobeni frekvence jednickou db CHANNEL_3_OPERATOR_2 + OPL_LEVEL, 0x00 ; nastaveni urovne vystupu nosne na 47 dB db CHANNEL_3_OPERATOR_2 + OPL_ATTACK_DECAY, 0xF0 ; nosna: rychly nastup + pomale doznivani db CHANNEL_3_OPERATOR_2 + OPL_SUSTAIN_RELEASE, 0x77 ; urovne sustain a release pro nosnou db CHANNEL_3 + OPL_FREQUENCY_LOW, 0xb0 ; frekvence zvuku (E) db CHANNEL_4_OPERATOR_1 + OPL_AMP_VIBRATO_EG, 0x01 ; nastaveni modulatoru: nasobeni frekvence jednickou db CHANNEL_4_OPERATOR_1 + OPL_LEVEL, 0x10 ; uroven vystupu 40 dB db CHANNEL_4_OPERATOR_1 + OPL_ATTACK_DECAY, 0x55 ; modulator: rychly nastup zvuku + pomale doznivani db CHANNEL_4_OPERATOR_1 + OPL_SUSTAIN_RELEASE, 0x77 ; urovne sustain a release pro modulator db CHANNEL_4_OPERATOR_2 + OPL_AMP_VIBRATO_EG, 0x01 ; nastaveni nosne: nasobeni frekvence jednickou db CHANNEL_4_OPERATOR_2 + OPL_LEVEL, 0x00 ; nastaveni urovne vystupu nosne na 47 dB db CHANNEL_4_OPERATOR_2 + OPL_ATTACK_DECAY, 0xF0 ; nosna: rychly nastup + pomale doznivani db CHANNEL_4_OPERATOR_2 + OPL_SUSTAIN_RELEASE, 0x77 ; urovne sustain a release pro nosnou db CHANNEL_4 + OPL_FREQUENCY_LOW, 0xca ; frekvence zvuku (F) db CHANNEL_5_OPERATOR_1 + OPL_AMP_VIBRATO_EG, 0x01 ; nastaveni modulatoru: nasobeni frekvence jednickou db CHANNEL_5_OPERATOR_1 + OPL_LEVEL, 0x10 ; uroven vystupu 40 dB db CHANNEL_5_OPERATOR_1 + OPL_ATTACK_DECAY, 0x55 ; modulator: rychly nastup zvuku + pomale doznivani db CHANNEL_5_OPERATOR_1 + OPL_SUSTAIN_RELEASE, 0x77 ; urovne sustain a release pro modulator db CHANNEL_5_OPERATOR_2 + OPL_AMP_VIBRATO_EG, 0x01 ; nastaveni nosne: nasobeni frekvence jednickou db CHANNEL_5_OPERATOR_2 + OPL_LEVEL, 0x00 ; nastaveni urovne vystupu nosne na 47 dB db CHANNEL_5_OPERATOR_2 + OPL_ATTACK_DECAY, 0xF0 ; nosna: rychly nastup + pomale doznivani db CHANNEL_5_OPERATOR_2 + OPL_SUSTAIN_RELEASE, 0x77 ; urovne sustain a release pro nosnou db CHANNEL_5 + OPL_FREQUENCY_LOW, 0x02 ; frekvence zvuku (G) db CHANNEL_6_OPERATOR_1 + OPL_AMP_VIBRATO_EG, 0x01 ; nastaveni modulatoru: nasobeni frekvence jednickou db CHANNEL_6_OPERATOR_1 + OPL_LEVEL, 0x10 ; uroven vystupu 40 dB db CHANNEL_6_OPERATOR_1 + OPL_ATTACK_DECAY, 0x55 ; modulator: rychly nastup zvuku + pomale doznivani db CHANNEL_6_OPERATOR_1 + OPL_SUSTAIN_RELEASE, 0x77 ; urovne sustain a release pro modulator db CHANNEL_6_OPERATOR_2 + OPL_AMP_VIBRATO_EG, 0x01 ; nastaveni nosne: nasobeni frekvence jednickou db CHANNEL_6_OPERATOR_2 + OPL_LEVEL, 0x00 ; nastaveni urovne vystupu nosne na 47 dB db CHANNEL_6_OPERATOR_2 + OPL_ATTACK_DECAY, 0xF0 ; nosna: rychly nastup + pomale doznivani db CHANNEL_6_OPERATOR_2 + OPL_SUSTAIN_RELEASE, 0x77 ; urovne sustain a release pro nosnou db CHANNEL_6 + OPL_FREQUENCY_LOW, 0x41 ; frekvence zvuku (A) db CHANNEL_7_OPERATOR_1 + OPL_AMP_VIBRATO_EG, 0x01 ; nastaveni modulatoru: nasobeni frekvence jednickou db CHANNEL_7_OPERATOR_1 + OPL_LEVEL, 0x10 ; uroven vystupu 40 dB db CHANNEL_7_OPERATOR_1 + OPL_ATTACK_DECAY, 0x55 ; modulator: rychly nastup zvuku + pomale doznivani db CHANNEL_7_OPERATOR_1 + OPL_SUSTAIN_RELEASE, 0x77 ; urovne sustain a release pro modulator db CHANNEL_7_OPERATOR_2 + OPL_AMP_VIBRATO_EG, 0x01 ; nastaveni nosne: nasobeni frekvence jednickou db CHANNEL_7_OPERATOR_2 + OPL_LEVEL, 0x00 ; nastaveni urovne vystupu nosne na 47 dB db CHANNEL_7_OPERATOR_2 + OPL_ATTACK_DECAY, 0xF0 ; nosna: rychly nastup + pomale doznivani db CHANNEL_7_OPERATOR_2 + OPL_SUSTAIN_RELEASE, 0x77 ; urovne sustain a release pro nosnou db CHANNEL_7 + OPL_FREQUENCY_LOW, 0x87 ; frekvence zvuku (B) db CHANNEL_8_OPERATOR_1 + OPL_AMP_VIBRATO_EG, 0x01 ; nastaveni modulatoru: nasobeni frekvence jednickou db CHANNEL_8_OPERATOR_1 + OPL_LEVEL, 0x10 ; uroven vystupu 40 dB db CHANNEL_8_OPERATOR_1 + OPL_ATTACK_DECAY, 0x55 ; modulator: rychly nastup zvuku + pomale doznivani db CHANNEL_8_OPERATOR_1 + OPL_SUSTAIN_RELEASE, 0x77 ; urovne sustain a release pro modulator db CHANNEL_8_OPERATOR_2 + OPL_AMP_VIBRATO_EG, 0x01 ; nastaveni nosne: nasobeni frekvence jednickou db CHANNEL_8_OPERATOR_2 + OPL_LEVEL, 0x00 ; nastaveni urovne vystupu nosne na 47 dB db CHANNEL_8_OPERATOR_2 + OPL_ATTACK_DECAY, 0xF0 ; nosna: rychly nastup + pomale doznivani db CHANNEL_8_OPERATOR_2 + OPL_SUSTAIN_RELEASE, 0x77 ; urovne sustain a release pro nosnou db CHANNEL_8 + OPL_FREQUENCY_LOW, 0xae ; frekvence zvuku (C) 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
11. Čip OPL3 z pohledu programátora
Nyní se konečně dostáváme k popisu čipu OPL3. Oproti výše popsanému čipu YM 3812 došlo k několika podstatným úpravám. Především se zvýšil celkový počet operátorů z osmnácti na 36, do jednoho kanálu je možné zapojit až čtyři operátory, místo čtyř typů signálů na vstupech operátorů je k dispozici osm typů (včetně obdélníkového signálu a logaritmicky zkresleného signálu pilového) a na výstup čipu je možné zapojit dvojici D/A převodníků a vytvářet tak stereo hudbu – ve skutečnosti však není možné plynule nastavovat přechod mezi levým a pravým reproduktorem (panning), lze pouze zvolit, zda je výstup z nějakého hudebního kanálu přehráván na levém, pravém či obou reproduktorech.
Vzhledem ke zvýšenému počtu operátorů se zvýšil i počet interních registrů. Z tohoto důvodu jsou místo jedné registrové sady použity sady dvě, což znamená, že místo dvou adres mapovaných do I/O prostoru (index a data) jsou použity adresy čtyři.
Zatímco u čipu YM 3812 bylo možné operátory v jednom kanálu zapojit pouze do dvou konfigurací (AM či FM), lze u čipu YMF 262 použít mnohem větší počet kombinací, kterými se budeme podrobněji zabývat příště. Existují tři možnosti konfigurace: 18 kanálů, z nichž každý obsahuje dva operátory, 15 melodických kanálů se dvěma operátory společně s pěti kanály pracujícími v perkusním režimu a konečně 6 kanálů se čtyřmi operátory (zbytek jsou buď dvouoperátorové kanály nebo kanály pracující v perkusním režimu).
V konfiguraci čtyřoperátorového kanálu vždy jeden z operátorů (původní modulátor) obsahuje zpětnou vazbu, i když v řídicích registrech je možné nastavit úroveň zpětné vazby pro všechny operátory – u tří čtvrtin operátorů nemá tedy obsah příslušného řídicího registru vliv na generovaný tón.
12. Řídicí registry čipu OPL3
Registrů čipu OPL3 je více než 256 a tudíž jsou pro jejich adresování+zápis použity čtyři I/O porty – vždy dva pro výběr registru a dva pro zápis dat do zvoleného registru. Dolních 256 registrů je ovládáno přes porty 0×220 a 0×221, horních pak přes porty 0×222 a 0×223:
Registr/registry | Dolní registry | Horní registry |
---|---|---|
01 | Test LSI / Enable waveform control | dtto |
02 | Timer 1 data | dtto |
03 | Timer 2 data | dtto |
04 | Timer control flags | konfigurace zvukových kanálů (2 operátory, 4 operátory, …) |
05 | nemá význam | kompatibilita s OPL2: ano/ne |
08 | Speech synthesis mode / Keyboard split note select | pravděpodobně bez významu |
20..35 | Amp Mod / Vibrato / EG type / Key Scaling / Multiple | dtto pro horních 18 operátorů |
40..55 | Key scaling level / Operator output level | dtto pro horních 18 operátorů |
60..75 | Attack Rate / Decay Rate | dtto pro horních 18 operátorů |
80..95 | Sustain Level / Release Rate | dtto pro horních 18 operátorů |
A0..A8 | Frequency (low 8 bits) | dtto pro horních 9 kanálů |
B0..B8 | Key On / Octave / Frequency (high 2 bits) | dtto pro horních 9 kanálů |
BD | AM depth / Vibrato depth / Rhythm control | nemá význam |
C0..C8 | Feedback strength / Connection type | dtto pro horních 9 kanálů |
E0..F5 | Wave Select | dtto pro horních 18 operátorů |
13. Stereo výstup
Z předchozího textu je pravděpodobně patrné, že čip OPL 3 nabízí mnohem více možností při vytváření zvuků, než původní OPL 2. Ovšem mnoho vývojářů nedokázalo všechny možnosti syntézy v tomto režimu využít – z tohoto důvodu se velmi často setkáme s tím, že je použita „dvouoperátorová“ syntéza a čip YMF 262 je tak vlastně degradován na stereo verzi původního čipu YM 3812 s dvojnásobným množstvím hudebních kanálů (osmnáct kanálů namísto devíti).
Na chvíli se zastavme právě u stereo výstupu. Do registrů OPL_FEEDBACK na adresách C0..C8 byly přidány dva bity, které určují, do jakého reproduktoru má být daný kanál vysílán – zvolit je možné libovolnou kombinaci levý+pravý (nebo i žádný). Tento registr má nyní tuto strukturu:
7 6 5 4 3 2 1 0 +-----+-----+-----+-----+-----+-----+-----+-----+ | ch. | ch. | R | L | Feedback | Alg | | D | C | out | out | | | +-----+-----+-----+-----+-----+-----+-----+-----+
Bity 7 a 6 volí výstupní kanály C a D (záleží na způsobu zapojení D/A převodníku).
Hodnotami bitů 5 a 4 se volí výstup do levého a/nebo pravého reproduktoru. Právě tyto bity budeme měnit.
Bity 3–1 nastavují sílu zpětné vazby, přičemž 0 znamená, že se zpětná vazba neuplatní a 7 znamená, že zpětnovazební signál má nejvyšší váhu.
Nultým bitem se volí způsob vzájemného propojení obou operátorů. FM (resp. přesněji řečeno PM) modulace je použita ve chvíli, kdy je tento bit nulový. Pokud je nastavený na jedničku, bude každý z operátorů pracovat nezávisle jako zdroj tónu (sinusovka nebo její varianty).
14. Demonstrační příklad: programová změna zvukového výstupu do levého, pravého i obou reproduktorů
Zkusme nyní jediný tón (konkrétně notu A) přehrát postupně v levém reproduktoru, potom v reproduktoru pravém a nakonec v obou reproduktorech. Měla by nám k tomu stačit tato sekvence maker, v nichž měníme bity 5 a 4 registru OPL_FEEDBACK pro první kanál:
; levy reproduktor write_opl_register CHANNEL_1 + OPL_FEEDBACK, 0b00010000 wait_key ; pravy reproduktor write_opl_register CHANNEL_1 + OPL_FEEDBACK, 0b00100000 wait_key ; oba reproduktory write_opl_register CHANNEL_1 + OPL_FEEDBACK, 0b00110000 wait_key
Úplný zdrojový kód tohoto demonstračního příkladu vypadá následovně:
; Prehrani zakladniho tonu na kartach s cipem OPL3. ; Prepinani vystupu na pravy a/nebo levy reproduktor. ; Pojmenovani registru OPL3. ; ; ; preklad pomoci: ; nasm -f bin -o sound_opl2_stereo1.com sound_opl3_stereo_1.asm ; ; nebo pouze: ; nasm -o sound_opl2_stereo1.com sound_opl3_stereo_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 ; 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 ;----------------------------------------------------------------------------- ; 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 nebo OPL3 %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_opl3 ; zapis obsahu tabulky do OPL2 ; levy reproduktor write_opl_register CHANNEL_1 + OPL_FEEDBACK, 0b00010000 wait_key ; pravy reproduktor write_opl_register CHANNEL_1 + OPL_FEEDBACK, 0b00100000 wait_key ; oba reproduktory write_opl_register CHANNEL_1 + OPL_FEEDBACK, 0b00110000 wait_key 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, 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 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
15. Nastavení čipu OPL3 do režimu NEkompatibilního s OPL2
Pokud demonstrační příklad z předchozí kapitoly přeložíme a spustíme, snadno zjistíme, že přepínání mezi reproduktory ve skutečnosti nefunguje. Proč tomu tak je? Čip OPL3 je po resetu nastaven do režimu kompatibilního s OPL2, v němž nemají vyšší bity registru OPL_FEEDBACK žádný zvláštní význam a tudíž jsou v kompatibilním režimu zcela ignorovány. Přepnutí do režimu NEkompatibilního s OPL2 je snadné – musíme nastavit nejnižší bit registru OPL3_MODE_ENABLE. Ten je – opět z důvodu zpětné kompatibility – umístěn mezi horních 256 řídicích registrů, takže ho kód určený pro původní OPL2 nemůže omylem přepsat.
Vypnutí režimu kompatibility:
write_opl_high_register OPL3_MODE_ENABLE, 1
Využíváme zde tuto konstantu:
OPL3_MODE_ENABLE equ 0x05 ; vyssi port!!!
A 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
16. Demonstrační příklad: funkční programový výběr zvukového výstupu
Následuje úplný zdrojový kód programu, který bude notu A postupně přehrávat v levém, potom v pravém a posléze v obou reproduktorech:
; Prehrani zakladniho tonu na kartach s cipem OPL3. ; Prepnuti do rezimu OPL3. ; Prepinani vystupu na pravy a/nebo levy reproduktor. ; Pojmenovani registru OPL3. ; ; ; preklad pomoci: ; nasm -f bin -o sound_opl2_stereo1.com sound_opl3_stereo_2.asm ; ; nebo pouze: ; nasm -o sound_opl2_stereo1.com sound_opl3_stereo_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 ;----------------------------------------------------------------------------- ; 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 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 OPL2 ; levy reproduktor write_opl_register CHANNEL_1 + OPL_FEEDBACK, 0b00010000 wait_key ; pravy reproduktor write_opl_register CHANNEL_1 + OPL_FEEDBACK, 0b00100000 wait_key ; oba reproduktory write_opl_register CHANNEL_1 + OPL_FEEDBACK, 0b00110000 wait_key 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, 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 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. Režim využívající 18 zvukových kanálů
Zvukové kanály čipu OPL3 mohou být nakonfigurovány čtyřmi různými způsoby:
- Osmnáct melodických kanálů, z nichž každý je tvořen dvěma operátory (jakoby bychom měli dva čipy OPL2)
- Patnáct melodických kanálů, z nichž každý je tvořen dvěma operátory + 5 kanálů pro perkusní nástroje (činely atd.)
- Až šest melodických kanálů, z nichž každý je tvořen čtyřmi operátory + minimálně šest kanálů tvořených dvěma operátory (čtyřoperátorové kanály lze povolovat individuálně)
- Až šest melodických kanálů, z nichž každý je tvořen čtyřmi operátory + tři kanály tvořené dvěma operátory + 5 kanálů pro perkusní nástroje (čtyřoperátorové kanály lze povolovat individuálně)
Prozatím využijeme první zmíněnou konfiguraci, tj. osmnáct melodických zvukových kanálů, přičemž zvuk v každém kanálu je tvořen dvěma operátory zapojenými buď v režimu AM syntézy či FM (PM) syntézy. Z těchto osmnácti kanálů využijeme celkem 16 kanálů – osm pro přehrání not v jedné oktávě, dalších osm pro přehrání stejných not, ovšem s mnohem větší mírou distorze FM syntézou. Všechny relevantní registry těchto šestnácti kanálů jsou v demonstračním příkladu (viz další kapitolu) uloženy v příslušných dvou tabulkách (pro „nižší“ kanály a pro kanály „vyšší“). A další tabulka obsahuje vazbu mezi stiskem/uvolněním klávesy a změnou OPL registru KEY_ON.
18. Demonstrační příklad: využití většiny zvukových kanálů čipu OPL3
Ukažme si nyní upravené „klávesy“, které dokážou přehrát dvě stupnice. První z nich se řídí klávesami 1–8 (první řada), druhá pak klávesami Q-I (druhá řada). Při přehrávání mohou nastat problémy kvůli ghostingu kláves, což je ovšem pro program ovládaný 18 klávesami prakticky neopravitelná vada. Zdrojový kód je sice poměrně dlouhý (25kB), ale výsledkem je .COM soubor o velikosti pouhých 550 bajtů, což stále není špatné (program navíc vůbec není optimalizován na velikost):
; Klavesami 1-8 lze prehrat noty z jedne oktavy (i soucasne). ; klavesami Q-I se prehraji noty s jinym zabarvenim. ; Kratsi varianta s tabulkou operaci, ktere se maji provest pri stisku klavesy. ; Pojmenovani registru OPL3. ; Zapisy do "dolnich" i "hornich" registru OPL3 ; ; ; preklad pomoci: ; nasm -f bin -o sound_opl2_table.com sound_opl3_multichannel.asm ; ; nebo pouze: ; nasm -o sound_opl2_table.com sound_opl3_multichannel.asm ;----------------------------------------------------------------------------- BITS 16 ; 16bitovy vystup pro DOS CPU 8086 ; specifikace pouziteho instrukcniho souboru ;----------------------------------------------------------------------------- ; registry karet s cipem OPL2 OPL_ADDRESS equ 0x388 OPL_DATA equ 0x389 OPL_HIGH_ADDRESS equ 0x222 OPL_HIGH_DATA equ 0x223 ; skupiny registru LOW_REGISTER equ 0 HIGH_REGISTER equ 1 ; 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_2 equ 0x03 KEY_3 equ 0x04 KEY_4 equ 0x05 KEY_5 equ 0x06 KEY_6 equ 0x07 KEY_7 equ 0x08 KEY_8 equ 0x09 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 %macro write_opl_register 2 mov al, %1 mov ah, %2 call perform_write_to_low_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_high_opl_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, tones_1 ; zacatek tabulky call write_table_to_low_registers ; zapis obsahu tabulky do OPL3 mov si, tones_2 ; zacatek tabulky call write_table_to_high_registers ; 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_ESC ; test na stisk ESC je .exit ; pokud stisknuta, konec programu mov ah, al ; kod klavesy do registru AH pro dalsi pouziti mov si, key_actions ; tabulka akci pri stisku ci uvolneni klavesy .next_key: lodsb ; nacist kod klavesy z tabulky or al, al ; test na nulu (zarazka) jz .opak ; nic jsme jiz nenasli -> cteni klavesy pres port cmp ah, al ; nasli jsme kod klavesy, ktery zname? jne .try_next_key lodsb ; horni nebo dolni registr? add al, al ; ZF -> dolni registry, jinak horni lodsb ; adresa OPL registru mov ah, al lodsb ; hodnota OPL registru xchg ah, al ; vtipne jsme si prohodili parametry subrutiny write_opl_register jnz .high_register call perform_write_to_low_opl_register jmp .next_key ; zkusit dalsi klavesu .high_register: call perform_write_to_high_opl_register jmp .next_key ; zkusit dalsi klavesu .try_next_key: add si, 3 ; preskocit typ a adresu registru + jeho hodnotu jmp .next_key .exit: exit write_table_to_low_registers: 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_low_opl_register jmp write_table_to_low_registers ; muzeme prejit na dalsi registr write_table_to_high_registers: 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_high_opl_register jmp write_table_to_high_registers ; muzeme prejit na dalsi registr key_actions: ; prvni rada klaves db KEY_1, LOW_REGISTER, CHANNEL_1 + OPL_KEY_ON, 0b00101110 db KEY_1+KEY_RELEASE, LOW_REGISTER, CHANNEL_1 + OPL_KEY_ON, 0b00001110 db KEY_2, LOW_REGISTER, CHANNEL_2 + OPL_KEY_ON, 0b00110001 db KEY_2+KEY_RELEASE, LOW_REGISTER, CHANNEL_2 + OPL_KEY_ON, 0b00010001 db KEY_3, LOW_REGISTER, CHANNEL_3 + OPL_KEY_ON, 0b00110001 db KEY_3+KEY_RELEASE, LOW_REGISTER, CHANNEL_3 + OPL_KEY_ON, 0b00010001 db KEY_4, LOW_REGISTER, CHANNEL_4 + OPL_KEY_ON, 0b00110001 db KEY_4+KEY_RELEASE, LOW_REGISTER, CHANNEL_4 + OPL_KEY_ON, 0b00010001 db KEY_5, LOW_REGISTER, CHANNEL_5 + OPL_KEY_ON, 0b00110010 db KEY_5+KEY_RELEASE, LOW_REGISTER, CHANNEL_5 + OPL_KEY_ON, 0b00010010 db KEY_6, LOW_REGISTER, CHANNEL_6 + OPL_KEY_ON, 0b00110010 db KEY_6+KEY_RELEASE, LOW_REGISTER, CHANNEL_6 + OPL_KEY_ON, 0b00010010 db KEY_7, LOW_REGISTER, CHANNEL_7 + OPL_KEY_ON, 0b00110010 db KEY_7+KEY_RELEASE, LOW_REGISTER, CHANNEL_7 + OPL_KEY_ON, 0b00010010 db KEY_8, LOW_REGISTER, CHANNEL_8 + OPL_KEY_ON, 0b00110010 db KEY_8+KEY_RELEASE, LOW_REGISTER, CHANNEL_8 + OPL_KEY_ON, 0b00010010 ; druha rada klaves db KEY_Q, HIGH_REGISTER, CHANNEL_1 + OPL_KEY_ON, 0b00101110 db KEY_Q+KEY_RELEASE, HIGH_REGISTER, CHANNEL_1 + OPL_KEY_ON, 0b00001110 db KEY_W, HIGH_REGISTER, CHANNEL_2 + OPL_KEY_ON, 0b00110001 db KEY_W+KEY_RELEASE, HIGH_REGISTER, CHANNEL_2 + OPL_KEY_ON, 0b00010001 db KEY_E, HIGH_REGISTER, CHANNEL_3 + OPL_KEY_ON, 0b00110001 db KEY_E+KEY_RELEASE, HIGH_REGISTER, CHANNEL_3 + OPL_KEY_ON, 0b00010001 db KEY_R, HIGH_REGISTER, CHANNEL_4 + OPL_KEY_ON, 0b00110001 db KEY_R+KEY_RELEASE, HIGH_REGISTER, CHANNEL_4 + OPL_KEY_ON, 0b00010001 db KEY_T, HIGH_REGISTER, CHANNEL_5 + OPL_KEY_ON, 0b00110010 db KEY_T+KEY_RELEASE, HIGH_REGISTER, CHANNEL_5 + OPL_KEY_ON, 0b00010010 db KEY_Y, HIGH_REGISTER, CHANNEL_6 + OPL_KEY_ON, 0b00110010 db KEY_Y+KEY_RELEASE, HIGH_REGISTER, CHANNEL_6 + OPL_KEY_ON, 0b00010010 db KEY_U, HIGH_REGISTER, CHANNEL_7 + OPL_KEY_ON, 0b00110010 db KEY_U+KEY_RELEASE, HIGH_REGISTER, CHANNEL_7 + OPL_KEY_ON, 0b00010010 db KEY_I, HIGH_REGISTER, CHANNEL_8 + OPL_KEY_ON, 0b00110010 db KEY_I+KEY_RELEASE, HIGH_REGISTER, CHANNEL_8 + OPL_KEY_ON, 0b00010010 db 0, 0 ; zarazka tones_1: ; tabulka s tony pro osm kanalu 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, 0x55 ; 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_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_FREQUENCY_LOW, 0xae ; frekvence zvuku (C) db CHANNEL_2_OPERATOR_1 + OPL_AMP_VIBRATO_EG, 0x01 ; nastaveni modulatoru: nasobeni frekvence jednickou db CHANNEL_2_OPERATOR_1 + OPL_LEVEL, 0x10 ; uroven vystupu 40 dB db CHANNEL_2_OPERATOR_1 + OPL_ATTACK_DECAY, 0x55 ; modulator: rychly nastup zvuku + pomale doznivani db CHANNEL_2_OPERATOR_1 + OPL_SUSTAIN_RELEASE, 0x77 ; urovne sustain a release pro modulator db CHANNEL_2_OPERATOR_2 + OPL_AMP_VIBRATO_EG, 0x01 ; nastaveni nosne: nasobeni frekvence jednickou db CHANNEL_2_OPERATOR_2 + OPL_LEVEL, 0x00 ; nastaveni urovne vystupu nosne na 47 dB db CHANNEL_2_OPERATOR_2 + OPL_ATTACK_DECAY, 0xF0 ; nosna: rychly nastup + pomale doznivani db CHANNEL_2_OPERATOR_2 + OPL_SUSTAIN_RELEASE, 0x77 ; urovne sustain a release pro nosnou db CHANNEL_2 + OPL_FREQUENCY_LOW, 0x81 ; frekvence zvuku (D) db CHANNEL_3_OPERATOR_1 + OPL_AMP_VIBRATO_EG, 0x01 ; nastaveni modulatoru: nasobeni frekvence jednickou db CHANNEL_3_OPERATOR_1 + OPL_LEVEL, 0x10 ; uroven vystupu 40 dB db CHANNEL_3_OPERATOR_1 + OPL_ATTACK_DECAY, 0x55 ; modulator: rychly nastup zvuku + pomale doznivani db CHANNEL_3_OPERATOR_1 + OPL_SUSTAIN_RELEASE, 0x77 ; urovne sustain a release pro modulator db CHANNEL_3_OPERATOR_2 + OPL_AMP_VIBRATO_EG, 0x01 ; nastaveni nosne: nasobeni frekvence jednickou db CHANNEL_3_OPERATOR_2 + OPL_LEVEL, 0x00 ; nastaveni urovne vystupu nosne na 47 dB db CHANNEL_3_OPERATOR_2 + OPL_ATTACK_DECAY, 0xF0 ; nosna: rychly nastup + pomale doznivani db CHANNEL_3_OPERATOR_2 + OPL_SUSTAIN_RELEASE, 0x77 ; urovne sustain a release pro nosnou db CHANNEL_3 + OPL_FREQUENCY_LOW, 0xb0 ; frekvence zvuku (E) db CHANNEL_4_OPERATOR_1 + OPL_AMP_VIBRATO_EG, 0x01 ; nastaveni modulatoru: nasobeni frekvence jednickou db CHANNEL_4_OPERATOR_1 + OPL_LEVEL, 0x10 ; uroven vystupu 40 dB db CHANNEL_4_OPERATOR_1 + OPL_ATTACK_DECAY, 0x55 ; modulator: rychly nastup zvuku + pomale doznivani db CHANNEL_4_OPERATOR_1 + OPL_SUSTAIN_RELEASE, 0x77 ; urovne sustain a release pro modulator db CHANNEL_4_OPERATOR_2 + OPL_AMP_VIBRATO_EG, 0x01 ; nastaveni nosne: nasobeni frekvence jednickou db CHANNEL_4_OPERATOR_2 + OPL_LEVEL, 0x00 ; nastaveni urovne vystupu nosne na 47 dB db CHANNEL_4_OPERATOR_2 + OPL_ATTACK_DECAY, 0xF0 ; nosna: rychly nastup + pomale doznivani db CHANNEL_4_OPERATOR_2 + OPL_SUSTAIN_RELEASE, 0x77 ; urovne sustain a release pro nosnou db CHANNEL_4 + OPL_FREQUENCY_LOW, 0xca ; frekvence zvuku (F) db CHANNEL_5_OPERATOR_1 + OPL_AMP_VIBRATO_EG, 0x01 ; nastaveni modulatoru: nasobeni frekvence jednickou db CHANNEL_5_OPERATOR_1 + OPL_LEVEL, 0x10 ; uroven vystupu 40 dB db CHANNEL_5_OPERATOR_1 + OPL_ATTACK_DECAY, 0x55 ; modulator: rychly nastup zvuku + pomale doznivani db CHANNEL_5_OPERATOR_1 + OPL_SUSTAIN_RELEASE, 0x77 ; urovne sustain a release pro modulator db CHANNEL_5_OPERATOR_2 + OPL_AMP_VIBRATO_EG, 0x01 ; nastaveni nosne: nasobeni frekvence jednickou db CHANNEL_5_OPERATOR_2 + OPL_LEVEL, 0x00 ; nastaveni urovne vystupu nosne na 47 dB db CHANNEL_5_OPERATOR_2 + OPL_ATTACK_DECAY, 0xF0 ; nosna: rychly nastup + pomale doznivani db CHANNEL_5_OPERATOR_2 + OPL_SUSTAIN_RELEASE, 0x77 ; urovne sustain a release pro nosnou db CHANNEL_5 + OPL_FREQUENCY_LOW, 0x02 ; frekvence zvuku (G) db CHANNEL_6_OPERATOR_1 + OPL_AMP_VIBRATO_EG, 0x01 ; nastaveni modulatoru: nasobeni frekvence jednickou db CHANNEL_6_OPERATOR_1 + OPL_LEVEL, 0x10 ; uroven vystupu 40 dB db CHANNEL_6_OPERATOR_1 + OPL_ATTACK_DECAY, 0x55 ; modulator: rychly nastup zvuku + pomale doznivani db CHANNEL_6_OPERATOR_1 + OPL_SUSTAIN_RELEASE, 0x77 ; urovne sustain a release pro modulator db CHANNEL_6_OPERATOR_2 + OPL_AMP_VIBRATO_EG, 0x01 ; nastaveni nosne: nasobeni frekvence jednickou db CHANNEL_6_OPERATOR_2 + OPL_LEVEL, 0x00 ; nastaveni urovne vystupu nosne na 47 dB db CHANNEL_6_OPERATOR_2 + OPL_ATTACK_DECAY, 0xF0 ; nosna: rychly nastup + pomale doznivani db CHANNEL_6_OPERATOR_2 + OPL_SUSTAIN_RELEASE, 0x77 ; urovne sustain a release pro nosnou db CHANNEL_6 + OPL_FREQUENCY_LOW, 0x41 ; frekvence zvuku (A) db CHANNEL_7_OPERATOR_1 + OPL_AMP_VIBRATO_EG, 0x01 ; nastaveni modulatoru: nasobeni frekvence jednickou db CHANNEL_7_OPERATOR_1 + OPL_LEVEL, 0x10 ; uroven vystupu 40 dB db CHANNEL_7_OPERATOR_1 + OPL_ATTACK_DECAY, 0x55 ; modulator: rychly nastup zvuku + pomale doznivani db CHANNEL_7_OPERATOR_1 + OPL_SUSTAIN_RELEASE, 0x77 ; urovne sustain a release pro modulator db CHANNEL_7_OPERATOR_2 + OPL_AMP_VIBRATO_EG, 0x01 ; nastaveni nosne: nasobeni frekvence jednickou db CHANNEL_7_OPERATOR_2 + OPL_LEVEL, 0x00 ; nastaveni urovne vystupu nosne na 47 dB db CHANNEL_7_OPERATOR_2 + OPL_ATTACK_DECAY, 0xF0 ; nosna: rychly nastup + pomale doznivani db CHANNEL_7_OPERATOR_2 + OPL_SUSTAIN_RELEASE, 0x77 ; urovne sustain a release pro nosnou db CHANNEL_7 + OPL_FREQUENCY_LOW, 0x87 ; frekvence zvuku (B) db CHANNEL_8_OPERATOR_1 + OPL_AMP_VIBRATO_EG, 0x01 ; nastaveni modulatoru: nasobeni frekvence jednickou db CHANNEL_8_OPERATOR_1 + OPL_LEVEL, 0x10 ; uroven vystupu 40 dB db CHANNEL_8_OPERATOR_1 + OPL_ATTACK_DECAY, 0x55 ; modulator: rychly nastup zvuku + pomale doznivani db CHANNEL_8_OPERATOR_1 + OPL_SUSTAIN_RELEASE, 0x77 ; urovne sustain a release pro modulator db CHANNEL_8_OPERATOR_2 + OPL_AMP_VIBRATO_EG, 0x01 ; nastaveni nosne: nasobeni frekvence jednickou db CHANNEL_8_OPERATOR_2 + OPL_LEVEL, 0x00 ; nastaveni urovne vystupu nosne na 47 dB db CHANNEL_8_OPERATOR_2 + OPL_ATTACK_DECAY, 0xF0 ; nosna: rychly nastup + pomale doznivani db CHANNEL_8_OPERATOR_2 + OPL_SUSTAIN_RELEASE, 0x77 ; urovne sustain a release pro nosnou db CHANNEL_8 + OPL_FREQUENCY_LOW, 0xae ; frekvence zvuku (C) db 0, 0 ; zarazka tones_2: ; tabulka s tony pro osm kanalu 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: rychly 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 + OPL_FREQUENCY_LOW, 0xae ; frekvence zvuku (C) db CHANNEL_2_OPERATOR_1 + OPL_AMP_VIBRATO_EG, 0x01 ; nastaveni modulatoru: nasobeni frekvence jednickou db CHANNEL_2_OPERATOR_1 + OPL_LEVEL, 0x00 ; uroven vystupu 40 dB db CHANNEL_2_OPERATOR_1 + OPL_ATTACK_DECAY, 0x41 ; modulator: rychly nastup zvuku + pomale doznivani db CHANNEL_2_OPERATOR_1 + OPL_SUSTAIN_RELEASE, 0x7f ; urovne sustain a release pro modulator db CHANNEL_2_OPERATOR_2 + OPL_AMP_VIBRATO_EG, 0x01 ; nastaveni nosne: nasobeni frekvence jednickou db CHANNEL_2_OPERATOR_2 + OPL_LEVEL, 0x00 ; nastaveni urovne vystupu nosne na 47 dB db CHANNEL_2_OPERATOR_2 + OPL_ATTACK_DECAY, 0xa2 ; nosna: rychly nastup + pomale doznivani db CHANNEL_2_OPERATOR_2 + OPL_SUSTAIN_RELEASE, 0x77 ; urovne sustain a release pro nosnou db CHANNEL_2 + OPL_FREQUENCY_LOW, 0x81 ; frekvence zvuku (D) db CHANNEL_3_OPERATOR_1 + OPL_AMP_VIBRATO_EG, 0x01 ; nastaveni modulatoru: nasobeni frekvence jednickou db CHANNEL_3_OPERATOR_1 + OPL_LEVEL, 0x00 ; uroven vystupu 40 dB db CHANNEL_3_OPERATOR_1 + OPL_ATTACK_DECAY, 0x41 ; modulator: rychly nastup zvuku + pomale doznivani db CHANNEL_3_OPERATOR_1 + OPL_SUSTAIN_RELEASE, 0x7f ; urovne sustain a release pro modulator db CHANNEL_3_OPERATOR_2 + OPL_AMP_VIBRATO_EG, 0x01 ; nastaveni nosne: nasobeni frekvence jednickou db CHANNEL_3_OPERATOR_2 + OPL_LEVEL, 0x00 ; nastaveni urovne vystupu nosne na 47 dB db CHANNEL_3_OPERATOR_2 + OPL_ATTACK_DECAY, 0xa2 ; nosna: rychly nastup + pomale doznivani db CHANNEL_3_OPERATOR_2 + OPL_SUSTAIN_RELEASE, 0x77 ; urovne sustain a release pro nosnou db CHANNEL_3 + OPL_FREQUENCY_LOW, 0xb0 ; frekvence zvuku (E) db CHANNEL_4_OPERATOR_1 + OPL_AMP_VIBRATO_EG, 0x01 ; nastaveni modulatoru: nasobeni frekvence jednickou db CHANNEL_4_OPERATOR_1 + OPL_LEVEL, 0x00 ; uroven vystupu 40 dB db CHANNEL_4_OPERATOR_1 + OPL_ATTACK_DECAY, 0x41 ; modulator: rychly nastup zvuku + pomale doznivani db CHANNEL_4_OPERATOR_1 + OPL_SUSTAIN_RELEASE, 0x7f ; urovne sustain a release pro modulator db CHANNEL_4_OPERATOR_2 + OPL_AMP_VIBRATO_EG, 0x01 ; nastaveni nosne: nasobeni frekvence jednickou db CHANNEL_4_OPERATOR_2 + OPL_LEVEL, 0x00 ; nastaveni urovne vystupu nosne na 47 dB db CHANNEL_4_OPERATOR_2 + OPL_ATTACK_DECAY, 0xa2 ; nosna: rychly nastup + pomale doznivani db CHANNEL_4_OPERATOR_2 + OPL_SUSTAIN_RELEASE, 0x77 ; urovne sustain a release pro nosnou db CHANNEL_4 + OPL_FREQUENCY_LOW, 0xca ; frekvence zvuku (F) db CHANNEL_5_OPERATOR_1 + OPL_AMP_VIBRATO_EG, 0x01 ; nastaveni modulatoru: nasobeni frekvence jednickou db CHANNEL_5_OPERATOR_1 + OPL_LEVEL, 0x00 ; uroven vystupu 40 dB db CHANNEL_5_OPERATOR_1 + OPL_ATTACK_DECAY, 0x41 ; modulator: rychly nastup zvuku + pomale doznivani db CHANNEL_5_OPERATOR_1 + OPL_SUSTAIN_RELEASE, 0x7f ; urovne sustain a release pro modulator db CHANNEL_5_OPERATOR_2 + OPL_AMP_VIBRATO_EG, 0x01 ; nastaveni nosne: nasobeni frekvence jednickou db CHANNEL_5_OPERATOR_2 + OPL_LEVEL, 0x00 ; nastaveni urovne vystupu nosne na 47 dB db CHANNEL_5_OPERATOR_2 + OPL_ATTACK_DECAY, 0xa2 ; nosna: rychly nastup + pomale doznivani db CHANNEL_5_OPERATOR_2 + OPL_SUSTAIN_RELEASE, 0x77 ; urovne sustain a release pro nosnou db CHANNEL_5 + OPL_FREQUENCY_LOW, 0x02 ; frekvence zvuku (G) db CHANNEL_6_OPERATOR_1 + OPL_AMP_VIBRATO_EG, 0x01 ; nastaveni modulatoru: nasobeni frekvence jednickou db CHANNEL_6_OPERATOR_1 + OPL_LEVEL, 0x00 ; uroven vystupu 40 dB db CHANNEL_6_OPERATOR_1 + OPL_ATTACK_DECAY, 0x41 ; modulator: rychly nastup zvuku + pomale doznivani db CHANNEL_6_OPERATOR_1 + OPL_SUSTAIN_RELEASE, 0x7f ; urovne sustain a release pro modulator db CHANNEL_6_OPERATOR_2 + OPL_AMP_VIBRATO_EG, 0x01 ; nastaveni nosne: nasobeni frekvence jednickou db CHANNEL_6_OPERATOR_2 + OPL_LEVEL, 0x00 ; nastaveni urovne vystupu nosne na 47 dB db CHANNEL_6_OPERATOR_2 + OPL_ATTACK_DECAY, 0xa2 ; nosna: rychly nastup + pomale doznivani db CHANNEL_6_OPERATOR_2 + OPL_SUSTAIN_RELEASE, 0x77 ; urovne sustain a release pro nosnou db CHANNEL_6 + OPL_FREQUENCY_LOW, 0x41 ; frekvence zvuku (A) db CHANNEL_7_OPERATOR_1 + OPL_AMP_VIBRATO_EG, 0x01 ; nastaveni modulatoru: nasobeni frekvence jednickou db CHANNEL_7_OPERATOR_1 + OPL_LEVEL, 0x00 ; uroven vystupu 40 dB db CHANNEL_7_OPERATOR_1 + OPL_ATTACK_DECAY, 0x41 ; modulator: rychly nastup zvuku + pomale doznivani db CHANNEL_7_OPERATOR_1 + OPL_SUSTAIN_RELEASE, 0x7f ; urovne sustain a release pro modulator db CHANNEL_7_OPERATOR_2 + OPL_AMP_VIBRATO_EG, 0x01 ; nastaveni nosne: nasobeni frekvence jednickou db CHANNEL_7_OPERATOR_2 + OPL_LEVEL, 0x00 ; nastaveni urovne vystupu nosne na 47 dB db CHANNEL_7_OPERATOR_2 + OPL_ATTACK_DECAY, 0xa2 ; nosna: rychly nastup + pomale doznivani db CHANNEL_7_OPERATOR_2 + OPL_SUSTAIN_RELEASE, 0x77 ; urovne sustain a release pro nosnou db CHANNEL_7 + OPL_FREQUENCY_LOW, 0x87 ; frekvence zvuku (B) db CHANNEL_8_OPERATOR_1 + OPL_AMP_VIBRATO_EG, 0x01 ; nastaveni modulatoru: nasobeni frekvence jednickou db CHANNEL_8_OPERATOR_1 + OPL_LEVEL, 0x00 ; uroven vystupu 40 dB db CHANNEL_8_OPERATOR_1 + OPL_ATTACK_DECAY, 0x41 ; modulator: rychly nastup zvuku + pomale doznivani db CHANNEL_8_OPERATOR_1 + OPL_SUSTAIN_RELEASE, 0x7f ; urovne sustain a release pro modulator db CHANNEL_8_OPERATOR_2 + OPL_AMP_VIBRATO_EG, 0x01 ; nastaveni nosne: nasobeni frekvence jednickou db CHANNEL_8_OPERATOR_2 + OPL_LEVEL, 0x00 ; nastaveni urovne vystupu nosne na 47 dB db CHANNEL_8_OPERATOR_2 + OPL_ATTACK_DECAY, 0xa2 ; nosna: rychly nastup + pomale doznivani db CHANNEL_8_OPERATOR_2 + OPL_SUSTAIN_RELEASE, 0x77 ; urovne sustain a release pro nosnou db CHANNEL_8 + OPL_FREQUENCY_LOW, 0xae ; frekvence zvuku (C) db 0, 0 ; zarazka perform_write_to_low_opl_register: ; zapis do vybraneho registru 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_high_opl_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
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 |
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