0,0 → 1,736 |
; |
; MenuetOS Driver (vmode.mdr) |
; Target: Vertical Refresh Rate programming and videomode changing |
; |
; Author: Trans <<<<<13>>>>> |
; Date: 20.07.2003 |
; |
; Version: 1.0 |
; OS: MenuetOS |
; Compiler: FASM |
; |
|
OS_BASE equ 0x80000000 |
|
use32 |
|
macro align value { rb (value-1) - ($ + value-1) mod value } |
|
org 0x80760000 |
|
headerstart=$ |
|
mdid db 'MDAZ' ; 4 byte id |
mdhver dd 0x00 ; header version |
mdcode dd MDSTART ; start of code |
mdver dd 0x00000001 ; driver version (subversion*65536+version) |
mdname db 'Trans VideoDriver' ; 32 bytes of full driver name |
times (32-($-mdname)) db ' ' ; |
|
headerlen=$-headerstart |
times (256-headerlen) db 0 ; reserved area for future |
|
MDSTART: ; start of driver code ( base_adr+256 bytes) |
; ebx(=ecx in program): |
; 1 - Get DriverInfo and Driver Initial Set |
; 2 - Get Current Video Mode With Vertical Refresh Rate |
; 3 - Change Video Mode |
; 4 - Return at Start System Video Mode |
; 5 - Change vertical and horizontal size of visible screen area |
; 6 - Change Vert/Hor position visible area on screen (not complete yet) |
; |
; MAXF - ... |
MAXF=5 |
|
;-------Main Manager------------- |
pushad |
cmp ebx,1 |
jb mdvm_00 |
cmp ebx,MAXF |
ja mdvm_00 |
shl ebx,2 |
add ebx,mdvm_func_table |
call dword [ebx] |
mov [esp+28],eax |
mov [esp+24],ecx |
mov [esp+20],edx |
mov [esp+16],ebx |
popad |
retn |
mdvm_00: |
popad |
xor eax,eax |
dec eax |
retn |
|
; ------Drivers Functions---------- |
|
align 4 |
|
; EBX=1 (in applications ECX=1)- Get DriverInfo and Driver Initial Set |
; |
; IN: ecx (in app. edx) - pointer to 512-bytes info area in application |
; OUT: |
; |
vm_info_init: |
push ecx |
cmp [mdrvm],dword 0 |
jnz .vmii_00 |
call vm_safe_reg |
call vm_get_initial_videomode |
mov eax,[initvm] |
mov [currvm],eax |
call vm_search_sys_func_table |
call vm_get_cur_vert_rate |
mov [initrr],eax |
call vm_calc_pixelclock |
call vm_calc_refrate |
inc [mdrvm] |
.vmii_00: |
pop ecx |
call vm_transfer_drv_info |
mov ebx,dword [refrate] |
mov eax,dword [mdid] ;dword [systlb] |
retn |
|
|
align 4 |
|
; EBX=2 (in applications ECX=2)- Get Current Video Mode |
; |
; OUT: eax = X_screen*65536+Y_screen |
; ebx = current vertical rate |
; ecx = current video mode (number) |
vm_get_cur_mode: |
cmp [mdrvm],dword 0 |
jz .vmgcm_00 |
call vm_get_cur_vert_rate |
mov eax,[OS_BASE+0FE00h] |
mov ebx,[OS_BASE+0FE04h] |
shl eax,16 |
add eax,ebx |
add eax,00010001h |
mov ebx,[refrate] |
mov ecx,[currvm] |
retn |
.vmgcm_00: |
xor eax,eax |
dec eax |
retn |
|
|
align 4 |
|
; EBX=3 (in applications ECX=3)- Change Video Mode |
; |
; IN: ecx = VertRate*65536+VideoMode |
; OUT: eax = 0 if no error |
; |
vm_set_video_mode: |
cmp [mdrvm],dword 0 |
jz .vmsvm_00 |
call vm_set_selected_mode |
; xor eax,eax |
retn |
.vmsvm_00: |
xor eax,eax |
dec eax |
retn |
|
|
align 4 |
|
; EBX=4 (in applications ECX=4)- Return at Start System Video Mode |
; |
; IN: |
; OUT: eax = = 0 if no error |
; |
vm_restore_init_video_mode: |
cmp [mdrvm],dword 0 |
jz .vmrivm_00 |
call vm_restore_reg |
xor eax,eax |
retn |
.vmrivm_00: |
xor eax,eax |
dec eax |
retn |
|
|
align 4 |
|
; EBX=5 (in applications ECX=5)- Change vertical and horizontal size |
; of visible screen area |
; IN: ecx (in app. edx) = 0/1 - -/+ horizontal size on 1 position |
; = 2/3 - -/+ vertical size on 1 position (8 pixels) |
; ^-^----- not complete yet |
; OUT: eax = = 0 if no error |
; |
vm_change_screen_size: |
cmp [mdrvm],dword 0 |
jz .vmcss_00 |
cmp cl,1 |
ja .vmcss_01 |
mov eax,ecx |
call vm_inc_dec_width |
xor eax,eax |
retn |
.vmcss_01: |
and ecx,01h |
mov eax,ecx |
; call vm_inc_dec_high ; not complete yet |
xor eax,eax |
retn |
.vmcss_00: |
xor eax,eax |
dec eax |
retn |
|
|
align 4 |
|
; EBX=6 (in applications ECX=6)- Change Vert/Hor position visible area on screen |
; |
; IN: ecx (in app. edx) = 0/1 - -/+ horizontal position on 1 point |
; = 2/3 - -/+ vertical position on 1 pixel |
; ^-^----- not complete yet |
; OUT: eax = 0 if no error |
; |
vm_change_position_screen: |
cmp [mdrvm],dword 0 |
jz .vmcps_00 |
; ... |
xor eax,eax |
retn |
.vmcps_00: |
xor eax,eax |
dec eax |
retn |
|
|
;-----Drivers Subfunctions--------- |
|
; |
; Searching i40 system functions pointer table in kernel area location |
; |
vm_search_sys_func_table: |
push eax ; eax - current value |
push ecx ; ecx - will be counter of equevalent value |
push edx ; edx - last value |
push esi ; esi - current address |
xor ecx,ecx |
mov esi,OS_BASE+010000h ; Start address of kernel location |
lodsd |
mov edx,eax |
cld |
.vmssft_00: |
cmp esi,OS_BASE+30000h |
ja .vmssft_03 |
inc ecx |
lodsd |
cmp edx,eax |
mov edx,eax |
je .vmssft_00 |
cmp ecx,128 |
ja .vmssft_02 |
.vmssft_01: |
xor ecx,ecx |
jmp .vmssft_00 |
.vmssft_02: |
cmp edx,0 |
je .vmssft_01 |
sub esi,256*4-1 |
mov [systlb],esi |
xor ecx,ecx |
.vmssft_03_0: |
inc ecx |
lodsd |
cmp edx,eax |
mov edx,eax |
jne .vmssft_03_0 |
mov esi,dword [systlb] |
cmp cx,60 |
jae .vmssft_03 |
add esi,256*4-4 |
lodsb |
mov edx,eax |
jmp .vmssft_01 |
.vmssft_03: |
mov [systlb],esi |
pop esi |
pop edx |
pop ecx |
pop eax |
retn |
|
; IN: |
; OUT: eax= vertical rate in Hz |
vm_get_cur_vert_rate: |
push edx |
push ebx |
xor eax,eax |
mov edx,eax |
mov ebx,eax |
mov dx,03DAh |
.vmgcvt_00: |
in al,dx |
test al,8 |
jz .vmgcvt_00 |
.vmgcvt_01: |
in al,dx |
test al,8 |
jnz .vmgcvt_01 |
mov ebx,edx |
rdtsc |
mov edx,ebx |
mov ebx,eax |
.vmgcvt_02: |
in al,dx |
test al,8 |
jz .vmgcvt_02 |
.vmgcvt_03: |
in al,dx |
test al,8 |
jnz .vmgcvt_03 |
rdtsc |
sub eax,ebx |
mov ebx,eax |
mov eax,[OS_BASE+0F600h] |
xor edx,edx |
div ebx |
inc eax |
mov [refrate],eax |
pop ebx |
pop edx |
retn |
|
vm_calc_pixelclock: |
push ebx |
push edx |
xor eax,eax |
mov al,[_00] |
add ax,5 |
shl eax,3 |
xor ebx,ebx |
mov bl,[_06] |
mov bh,[_07] |
and bh,00100001b |
btr bx,13 |
jnc .vmcpc_00 |
or bh,2 |
.vmcpc_00: |
xor edx,edx |
mul ebx |
xor edx,edx |
mul [initrr] |
mov [pclock],eax |
pop edx |
pop ebx |
retn |
|
; |
; Safe of initial CRTC state |
; |
vm_safe_reg: |
push edx |
push ebx |
push ecx |
push edi |
cli |
mov dx,3d4h ; CRTC |
mov al,11h |
out dx,al |
inc dx |
in al,dx |
and al,7fh |
out dx,al ; Clear protection bit |
dec dx |
xor ecx,ecx |
mov cl,19h |
xor bl,bl |
mov edi,CRTCreg |
.vmsr_00: |
mov al,bl |
out dx,al |
inc dx |
in al,dx |
dec dx |
stosb |
inc bl |
loop .vmsr_00 |
sti |
pop edi |
pop ecx |
pop ebx |
pop edx |
retn |
|
; |
; Restore of initial CRTC state |
; |
vm_restore_reg: |
push eax |
push ebx |
push edx |
push esi |
mov eax,[oldX] |
mov [OS_BASE+0FE00h],eax |
mov eax,[oldY] |
mov [OS_BASE+0FE04h],eax |
mov dx,03dah |
.vmrr_00: |
in al,dx |
test al,8 |
jnz .vmrr_00 |
.vmrr_01: |
in al,dx |
test al,8 |
jnz .vmrr_01 |
cli |
mov dx,03c4h |
mov ax,0101h |
out dx,ax |
mov dx,3d4h ; CRTC |
mov al,11h |
out dx,al |
inc dx |
in al,dx |
and al,7fh ; Clear Protection bit |
out dx,al |
dec dx |
xor ecx,ecx |
mov cl,19h |
mov esi,CRTCreg |
xor bl,bl |
.vmrr_02: |
lodsb |
mov ah,al |
mov al,bl |
out dx,ax |
inc bl |
loop .vmrr_02 |
sti |
; call ref_screen |
pop esi |
pop edx |
pop ecx |
pop eax |
retn |
|
; Calculate of possible vertical refrash rate |
; (light version of function) |
vm_calc_refrate: |
push ebx |
push ecx |
push edx |
push edi |
push esi |
mov eax,[pclock] |
xor edx,edx |
mov edi,_m1 |
mov ebx,eax |
mov ecx,(1696*1065) |
div ecx |
xor edx,edx |
stosw |
add edi,8 |
mov eax,ebx |
mov ecx,(1344*804) |
div ecx |
xor edx,edx |
stosw |
add edi,8 |
mov eax,ebx |
mov ecx,(1056*636) |
div ecx |
xor edx,edx |
stosw |
add edi,8 |
mov eax,ebx |
mov ecx,(800*524) |
div ecx |
xor edx,edx |
stosw |
mov edi,_m1 |
mov esi,edi |
mov ecx,5*4 |
.vmcrr_00: |
lodsw |
cmp ax,55 |
jb .vmcrr_01 |
stosw |
loop .vmcrr_00 |
pop esi |
pop edi |
pop edx |
pop ecx |
pop ebx |
retn |
.vmcrr_01: |
xor ax,ax |
stosw |
loop .vmcrr_00 |
pop esi |
pop edi |
pop edx |
pop ecx |
pop ebx |
retn |
|
vm_get_initial_videomode: |
push eax |
mov eax,dword [OS_BASE+0FE00h] |
mov [oldX],eax |
mov eax,dword [OS_BASE+0FE04h] |
mov [oldY],eax |
mov eax,dword [OS_BASE+0FE0Ch] ; initial video mode |
and ax,01FFh |
mov dword [initvm],eax |
pop eax |
retn |
|
|
; IN: eax = 0/1 - -/+ 1 position of width |
vm_inc_dec_width: |
push ebx |
push edx |
mov ebx,eax |
mov dx,3d4h ; CRTC |
mov al,11h |
out dx,al |
inc dx |
in al,dx |
and al,7fh ; Clear Protection bit |
out dx,al |
dec dx |
xor al,al |
out dx,al |
inc dx |
in al,dx |
dec al |
cmp bl,0 |
jnz .vmidr_00 |
inc al |
inc al |
.vmidr_00: |
out dx,al |
pop edx |
pop ebx |
retn |
|
; |
; Copy driver info to application area |
; |
; IN: ecx (in app. edx) - pointer to 512-bytes info area in application |
; OUT: |
vm_transfer_drv_info: |
push ecx |
push edi |
push esi |
mov eax,ecx |
xor ecx,ecx |
mov cl,32/4 |
mov esi,mdname |
mov edi,drvname |
rep movsd |
mov ecx,eax |
mov eax,[mdver] |
mov [drvver],eax |
mov edi,[OS_BASE+3010h] |
mov edi,[edi+10h] |
add edi,ecx |
mov esi,drvinfo |
xor ecx,ecx |
mov cx,512 |
rep movsb |
pop esi |
pop edi |
pop ecx |
retn |
|
|
; |
; Set selected video mode |
; (light version) |
; |
; IN: ecx = VertRate*65536+VideoMode |
; |
vm_set_selected_mode: |
push edx |
push ecx |
push esi |
ror ecx,16 |
cmp cx,00h |
je .vmssm_03 |
rol ecx,16 |
mov eax,ecx |
shl eax,16 |
shr eax,16 |
mov [currvm],eax |
cmp cx,112h |
jne .vmssm_00 |
mov esi,mode0 |
mov ecx,639 |
mov edx,479 |
jmp .vmssm_st00 |
.vmssm_00: |
cmp cx,115h |
jne .vmssm_01 |
mov esi,mode1 |
mov ecx,799 |
mov edx,599 |
jmp .vmssm_st00 |
.vmssm_01: |
cmp cx,118h |
jne .vmssm_02 |
mov esi,mode2 |
mov ecx,1023 |
mov edx,767 |
jmp .vmssm_st00 |
.vmssm_02: |
cmp cx,11Bh |
jne .vmssm_03 |
mov esi,mode2 |
mov ecx,1279 |
mov edx,1023 |
jmp .vmssm_st00 |
.vmssm_03: |
xor eax,eax |
dec eax |
pop esi |
pop ecx |
pop edx |
retn |
.vmssm_st00: |
mov [OS_BASE+0FE00h],ecx |
mov [OS_BASE+0FE04h],edx |
cli |
mov dx,03c4h |
lodsw |
out dx,ax |
mov dx,03d4h |
mov al,11h |
out dx,al |
inc dx |
in al,dx |
and al,7fh |
out dx,al |
dec dx |
mov ecx,13 |
.vmssm_st01: |
lodsw |
out dx,ax |
loop .vmssm_st01 |
sti |
xor eax,eax |
pop esi |
pop ecx |
pop edx |
retn |
|
|
;------------DATA AREA--------------- |
align 4 |
|
mdvm_func_table: |
dd MDSTART |
dd vm_info_init, vm_get_cur_mode |
dd vm_set_video_mode, vm_restore_init_video_mode |
dd vm_change_screen_size, vm_change_position_screen |
|
|
CRTCreg: |
_00 db ? |
_01 db ? |
_02 db ? |
_03 db ? |
_04 db ? |
_05 db ? |
_06 db ? |
_07 db ? |
_08 db ? |
_09 db ? |
_0a db ? |
_0b db ? |
_0c db ? |
_0d db ? |
_0e db ? |
_0f db ? |
_10 db ? |
_11 db ? |
_12 db ? |
_13 db ? |
_14 db ? |
_15 db ? |
_16 db ? |
_17 db ? |
_18 db ? |
_19 db ? |
|
align 4 |
|
oldX dd ? |
oldY dd ? |
initvm dd ? |
currvm dd 0 |
refrate dd 0 |
initrr dd 0 |
systlb dd 0 |
pclock dd ? |
mdrvm dd 0 ; 0 - not drv init yet, 1 - already drv init |
|
|
drvinfo: |
drvname: times 32 db ' ' |
drvver dd 0 |
times (32-($-drvver))/4 dd 0 |
drvmode dw 011Bh,0118h,0115h,0112h |
times (64-($-drvmode))/2 dw 00h |
_m1 dw 0,0,0,0,0 |
_m2 dw 0,0,0,0,0 |
_m3 dw 0,0,0,0,0 |
_m4 dw 0,0,0,0,0 |
_m5 dw 0,0,0,0,0 |
times (512-($-drvinfo)) db 0 |
drvinfoend: |
|
|
;1280x1024 - 11Bh |
mode3: |
dw 0101h |
dw 0d000h,9f01h,9f02h,9303h,0a904h,1905h,2806h,5a07h |
dw 0110h,8411h,0ff12h,0ff15h,2916h |
|
;1024x768 - 118h |
mode2: |
dw 0101h |
dw 0a400h,7f01h,7f02h,8703h,8404h,9505h,2406h,0f507h |
dw 0310h,8911h,0ff12h,0ff15h,2516h |
|
;800x600 - 115h |
mode1: |
dw 0101h |
dw 8000h,6301h,6302h,8303h,6a04h,1a05h,7206h,0f007h |
dw 5910h,8d11h,5712h,5715h,7316h |
|
;640x480 - 112h, 12h |
mode0: |
dw 0101h |
dw 6000h,4f01h,4f02h,8303h,5304h,9f05h,00b06h,3e07h |
dw 0ea10h,8c11h,0df12h,0df15h,0c16h |
|
; 640x400 |
;mymode0: |
; dw 0101h |
;_0_7 dw 5f00h,4f01h,4f02h,8303h,5304h,9f05h,0BF06h,1f07h |
; dw 9c10h,8e11h,8f12h,9615h,0B916h ;,4013h |
|
; 640x800 |
;mymode1: |
; dw 0101h |
; dw 5f00h,4f01h,4f02h,8003h,5004h,9f05h,06006h,0FF07h |
; dw 2d10h,8f11h,2012h,2615h,05716h ;,4013h |
|
|
DRVM_END: |
|