mirror of
https://github.com/ondra-novak/gates_of_skeldal.git
synced 2025-07-04 21:50:38 -04:00
304 lines
12 KiB
NASM
304 lines
12 KiB
NASM
.model small
|
|
.386P
|
|
|
|
DGROUP group _DATA
|
|
|
|
;real procedura pro prehravani na PCSPEAKERu.
|
|
;Tato procedura musi obsahovat vsechny deklarace, ktere vyuziva Protect Mode
|
|
;Tyto deklarace jsou pristupne i s PM. Opacne to vsak nelze
|
|
|
|
rl_pm_bufseg equ (offset pm_bufseg-rm_proc)
|
|
rl_bufseg equ (offset bufseg-rm_proc)
|
|
rl_bufpos equ (offset bufpos-rm_proc)
|
|
rl_port equ (offset port-rm_proc)
|
|
rl_xlattab equ (offset xlattab-rm_proc)
|
|
|
|
|
|
_TEXT16 segment byte public 'CODE' use16
|
|
assume cs:_TEXT16
|
|
assume ds:_TEXT16
|
|
rm_proc: ;Zde zacina obsluha INT 8 z realu
|
|
cli
|
|
push ds ;Program nevstupuje do dalsich int kvuly zdrzovani
|
|
push ax ;Nejprve se ulozi vsechny ohrozene registry
|
|
push bx
|
|
push dx
|
|
push si
|
|
mov ax,cs:[rl_bufseg]
|
|
mov ds,ax ;ds segment ukazuje na buffer
|
|
mov dx,cs:[rl_port] ;nacti adresu portu
|
|
lea bx,cs:[rl_xlattab];nacti zacatek
|
|
mov si,cs:[rl_bufpos];nacti si - adresu prehravaneho bytu
|
|
lods ds:[si] ;precti byte
|
|
mov cs:[rl_bufpos],si;uloz si
|
|
add bl,al
|
|
adc bh,0
|
|
mov al,cs:[bx]
|
|
out dx,al ;posli ho na port
|
|
mov al,20h
|
|
out 20h,al ;posli end of interrupt
|
|
pop si ;obnov se ulozene.
|
|
pop dx
|
|
pop bx
|
|
pop ax
|
|
pop ds
|
|
iret
|
|
|
|
bufseg dw 0x1234 ;segment kde je ulozen playing buffer
|
|
;predpoklada se ze je 64Kb dlouhy.
|
|
bufpos dw ? ;ukazatel na aktualni prehravana data
|
|
;data jsou v bufferu ulozena unsigned
|
|
port dw ? ;cislo portu, kam je nutne data posilat
|
|
pm_bufseg dw ? ;buffer z protectu
|
|
xlattab db 256 dup (?) ;prekladova tabulka pro PC_SPEAK.
|
|
;pro DAC vyplnte cisli 0 - 255
|
|
|
|
rm_konec: ;ukazatel na konec rm_proc
|
|
_TEXT16 ends
|
|
|
|
|
|
.data
|
|
|
|
old8rmofs dw ?
|
|
old8rmseg dw ?
|
|
old8pmofs dd ?
|
|
old8pmseg dw ?
|
|
|
|
rmproc_rmseg dw ? ;segment rm_proc v realnem rezimu
|
|
rmproc_pmseg dw ? ;segment rm_proc v chranenem rezim
|
|
|
|
timer dw ? ;hodnota casovace pro simulaci puvodni INT 8
|
|
timer_max dw ? ;max hodnota casovace
|
|
|
|
zavora db 0 ;zavora do pm_proc
|
|
|
|
SPKTAB Db 20h, 1fh, 1eh, 1dh, 1ch, 1bh, 1ah, 19h, 18h, 17h, 16h, 15h, 14h, 13h
|
|
Db 12h, 11h, 11h, 10h, 10h, 0fh, 0fh, 0eh, 0eh, 0dh, 0dh, 0dh, 0ch, 0ch, 0ch, 0ch
|
|
Db 0bh, 0bh, 0bh, 0bh, 0Ah, 0ah, 0ah, 0ah, 0ah, 09h, 09h, 09h, 09h, 09h, 09h, 09h
|
|
Db 09h, 08h, 08h, 08h, 08h, 08h, 08h, 08h, 08h, 08h, 08h, 08h, 08h, 08h, 07h, 07h
|
|
Db 07h, 07h, 07h, 07h, 07h, 06h, 06h, 06h, 06h, 06h, 06h, 06h, 06h, 06h, 06h, 06h
|
|
Db 05h, 05h, 05h, 05h, 05h, 05h, 05h, 05h, 05h, 05h, 04h, 04h, 04h, 04h, 04h, 04h
|
|
Db 04h, 04h, 04h, 04h, 03h, 03h, 03h, 03h, 03h, 03h, 03h, 03h, 03h, 03h, 02h, 02h
|
|
Db 02h, 02h, 02h, 02h, 02h, 02h, 02h, 01h, 01h, 01h, 01h, 01h, 01h, 01h, 01h, 01h
|
|
Db 01h, 01h ;prekladova tabulka pro speakra.
|
|
db 40h, 40h, 40h, 40h, 40h, 40h, 40h, 40h, 40h, 40h, 3fh, 3fh, 3fh, 3fh
|
|
Db 3fh, 3fh, 3fh, 3fh, 3fh, 3fh, 3fh, 3eh, 3eh, 3eh, 3eh, 3eh, 3eh, 3eh, 3eh, 3eh
|
|
Db 3eh, 3eh, 3dh, 3dh, 3dh, 3dh, 3dh, 3dh, 3dh, 3dh, 3dh, 3ch, 3ch, 3ch, 3ch, 3ch
|
|
Db 3ch, 3ch, 3ch, 3ch, 3ch, 3bh, 3bh, 3bh, 3bh, 3bh, 3bh, 3bh, 3bh, 3bh, 3bh, 3ah
|
|
Db 3ah, 3ah, 3ah, 3ah, 3ah, 3ah, 3ah, 3ah, 3ah, 39h, 39h, 39h, 39h, 39h, 39h, 39h
|
|
Db 39h, 39h, 39h, 38h, 38h, 38h, 38h, 38h, 38h, 38h, 38h, 37h, 37h, 37h, 37h, 37h
|
|
Db 36h, 36h, 36h, 36h, 35h, 35h, 35h, 35h, 34h, 34h, 34h, 33h, 33h, 32h, 32h, 31h
|
|
Db 31h, 30h, 30h, 2fh, 2eh, 2dh, 2ch, 2bh, 2ah, 29h, 28h, 27h, 26h, 25h, 24h, 23h
|
|
Db 22h, 21h
|
|
|
|
|
|
_TEXT segment byte public 'CODE' use32
|
|
assume CS:_TEXT
|
|
assume DS:DGROUP
|
|
|
|
public load_rm_proc_ ;funkce nacte rm_proc do realne pameti
|
|
load_rm_proc_ :
|
|
mov ebx,(rm_konec-rm_proc+16) shr 4 ;velikost v paragrafech
|
|
mov eax,100h
|
|
int 31h ;alokuj DOS pamet
|
|
mov rmproc_rmseg,ax ;segment
|
|
mov rmproc_pmseg,dx ;selektor
|
|
sbb al,al ;al=0xff pri chybe
|
|
jc lrmp_e ;skok pri chybe
|
|
push es ;uchovej segmentove registry
|
|
push ds
|
|
mov es,dx
|
|
xor edi,edi
|
|
mov dx,ds
|
|
mov ds,dx
|
|
mov esi,offset rm_proc
|
|
mov ecx,(rm_konec-rm_proc)
|
|
rep movsb ;presun rm_proc z protect mem do real mem
|
|
pop ds
|
|
pop es
|
|
lrmp_e: ret
|
|
|
|
public purge_rm_proc_ ;funkce uvolni rm_proc z pameti
|
|
purge_rm_proc_:
|
|
mov dx,rmproc_pmseg
|
|
mov eax,101h
|
|
int 31h ;dealokuj
|
|
sbb al,al ;al obsahuje chybu
|
|
ret
|
|
;tutu proceduru je nutne volat jako posledni!
|
|
|
|
public rm_proc_set_ ;funkce nastavuje promenne v rm_proc
|
|
;ax - bufseg - rm adresa bufferu
|
|
;dx - bufseg - pm adresa bufferu
|
|
;cx - adresa portu
|
|
;bx - mod XLAT - 0 normal mode
|
|
; 1 pcspeak mode
|
|
assume es:_TEXT16
|
|
rm_proc_set_:
|
|
push es ;uloz es
|
|
mov si,ds ;seg bufseg
|
|
mov es,si
|
|
mov es:bufseg,ax ;zapis rm bufseg
|
|
mov es:pm_bufseg,dx ;zapis pm bufseg
|
|
mov es:port,cx ;zapis cislo portu
|
|
or bx,bx ;test bx
|
|
jz rps_nrm ;je li nulovy - normal mode
|
|
lea esi,SPKTAB ;vem spktab
|
|
lea edi,es:xlattab
|
|
mov ecx,256
|
|
rep movsb ;prenes ji do xlattab
|
|
jmp rps_pcs
|
|
rps_nrm:xor ah,ah ;al =0
|
|
mov al,80h
|
|
lea edi,es:xlattab
|
|
rps_nr1:stosb ;zapis al do xlattab
|
|
inc al ;al=al+1
|
|
inc ah
|
|
jnz rps_nr1 ;dokud to nebude cela tabulka
|
|
rps_pcs:pop es ;obnov es
|
|
ret
|
|
;POZNAMKA: tato procedura modifikuje data v originalnim vzoru. Proto ji je
|
|
;nutne volat pred vlastnim load_rm_proc
|
|
|
|
pc_speak_protect: ;funkce pro obsluhu pcspeak v protect mode
|
|
push ds
|
|
push es ;uchovej ohrozene registry
|
|
push eax
|
|
push ebx
|
|
push edx
|
|
push esi
|
|
mov ax,seg _DATA
|
|
mov ds,ax
|
|
mov ds,ds:rmproc_pmseg ;nacti ukazatel na datovou oblast v rmm
|
|
assume ds:_TEXT16
|
|
mov ebx,rl_xlattab ;nacti ukazatel na xlattab
|
|
movzx edx,word ptr ds:[rl_port] ;nacti cislo portu
|
|
movzx esi,word ptr ds:[rl_bufpos] ;nacti ukazatel na vzorek
|
|
mov es,word ptr ds:[rl_pm_bufseg] ;nacti pm_selector na buffer
|
|
lods byte ptr [es:esi];precti sample
|
|
mov word ptr ds:[rl_bufpos],si;uloz ukazatel na dalsi vzorek
|
|
xlatb ;preloz podle xlattab
|
|
out dx,al ;posli ho na port
|
|
mov ax,seg _DATA ;vem selector na globalni data
|
|
mov ds,ax ;napln jim ds
|
|
assume ds:DGROUP
|
|
mov al,20h ;posli eoi
|
|
out 20h,al
|
|
dec timer ;sniz citac
|
|
jnz pcs_p1 ;pokud neni na nule, skoc na konec
|
|
mov ax,timer_max ;napln citac maximalni hodnotou
|
|
mov timer,ax
|
|
cmp zavora,0 ;odtestuj zavoru
|
|
jnz pcs_p1 ;zavrena zavora by zpusobila preplneni INT8
|
|
mov zavora,1 ;zavri zavoru
|
|
pushfd ;uchovej flagy - simuluj INT
|
|
sti ;povol preruseni (vsechna preruseni na INT8 projdou zavorou)
|
|
call far dword ptr[old8pmofs] ;skok do puvodniho osetreni INT8
|
|
mov zavora,0 ;zakazovat int neni treba, jeho stav je ulozen ve flags
|
|
pcs_p1: pop esi ;otevri zavoru - obnov registry
|
|
pop edx
|
|
pop ebx
|
|
pop eax
|
|
pop es
|
|
pop ds
|
|
iretd ;konec obsluhy preruseni.
|
|
|
|
public pc_speak_run_ ;funkce instaluje bimodalni ovladac PCSPEAK
|
|
pc_speak_run_:
|
|
;eax - sample freq
|
|
;edx - frekvence simulace int 8 (18.2 HZ)
|
|
cli ;zakaz preruseni
|
|
push eax ;tyto parametry zatim nejsou potreba
|
|
push edx
|
|
mov eax,200h ;nejprve zjisti puvodni obsluhu RM
|
|
mov bl,8 ;INT 8
|
|
int 31h
|
|
mov old8rmofs,dx ;uloz hodnoty
|
|
mov old8rmseg,cx
|
|
mov eax,204h ;pak precti starou obsluhu PM
|
|
int 31h
|
|
mov old8pmofs,edx ;uloz hodnoty
|
|
mov old8pmseg,cx
|
|
mov eax,205h ;nastav novou obsluju PM
|
|
mov cx,cs
|
|
mov edx,offset pc_speak_protect
|
|
int 31h
|
|
mov eax,201h ;nastav novou obsluhu RM
|
|
mov cx,rmproc_rmseg
|
|
mov dx,0
|
|
int 31h
|
|
pop ebx ;obnov sample freq
|
|
pop eax ;obnov simint freq -> do ebx!
|
|
mov ecx,eax ;sample freq uchovej jeste v ecx
|
|
xor edx,edx ;vynuluj edx, horni polovina edx&eax
|
|
div ebx ;delenim ziskej timer (samplef/simintf)
|
|
mov timer,ax ;uloz timer -> deleni neni presne ale v ramci
|
|
mov timer_max,ax ;presnosti vyhovuje
|
|
mov eax,1234dch ;ziskej nastaveni 8253 delenim zakladni freqvence
|
|
xor edx,edx
|
|
div ecx ;to je ted v eax
|
|
mov ecx,eax ;uchovej ho v ecx
|
|
mov al,34h ;citac 1 word rezim 2 - 1:m
|
|
out 43h,al ;zapis nastaveni
|
|
mov al,cl ;dolni hodnotu citace
|
|
out 40h,al
|
|
mov al,ch ;horni hodnotu citace
|
|
out 40h,al
|
|
sti ;povol preruseni
|
|
ret
|
|
|
|
|
|
public pc_speak_stop_ ;tato funkce zasatvi prehravani PCSPEAK a vrati puvodni vektory
|
|
pc_speak_stop_:
|
|
cli
|
|
mov al,36h ;nejprve zpomal casovace
|
|
out 43h,al
|
|
mov al,0
|
|
out 40h,al
|
|
out 40h,al
|
|
mov bl,8
|
|
mov eax,201h ;vrat puvodni rm vektor
|
|
mov cx,old8rmseg
|
|
mov dx,old8rmofs
|
|
int 31h
|
|
mov eax,205h ;vrat puvodni pm vektor
|
|
mov cx,old8pmseg
|
|
mov edx,old8pmofs
|
|
int 31h
|
|
sti
|
|
ret
|
|
|
|
public pc_speak_enable_ ;povoluje prehravani na PCSpeaker(TM)
|
|
pc_speak_enable_: ;nastavuje specialni rezim prehravani.
|
|
in al,61H
|
|
or al,3
|
|
out 61H,al
|
|
mov AL,90H
|
|
out 43H,al
|
|
ret
|
|
|
|
public pc_speak_disable_ ;zakazuje prehravani na PCSpeaker(TM)
|
|
pc_speak_disable_: ;funkce defacto vraci puvodni nastaveni.
|
|
SPKOFF: in al,061H
|
|
and al,0FCH
|
|
out 61H,al
|
|
ret
|
|
|
|
public pc_speak_position_ ;ziska aktualni pozici
|
|
pc_speak_position_:
|
|
push es
|
|
mov es,rmproc_pmseg
|
|
movzx eax,word ptr es:[rl_bufpos]
|
|
movzx ebx,word ptr es:[rl_bufseg]
|
|
shl ebx,4
|
|
add eax,ebx
|
|
pop es
|
|
ret
|
|
|
|
public pc_speak_set_proc_ ;zapise na [edi] adresi na pc_speak_position_
|
|
pc_speak_set_proc_:
|
|
mov [edi],offset pc_speak_position_
|
|
ret
|
|
|
|
_TEXT ends
|
|
end
|