; ; 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 ; use32 __DEBUG__ = 1 ;macro align value { rb (value-1) - ($ + value-1) mod value } macro func name { if used name align 4 name@of@func equ name ; _numb `name,name } macro begin { align 4 name@of@func: } endf fix end if macro return _val { if ~_val eq eax mov eax,_val end if ret } macro comment symb { ;s if 0=1 } ^ fix end if include 'struct.inc' B_HOST fix HOST_BENDIAN ; HOST_LENDIAN ;----------------------------------------------------------------------------- org 0x760000 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=7 ;-------Main Manager------------- pushad cmp ebx,1 jb mdvm_00 cmp ebx,MAXF ja mdvm_00 call dword [mdvm_func_table+ebx*4] 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---------- ; 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: ; func vm_info_init begin 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 endf ; 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) func vm_get_cur_mode begin cmp [mdrvm],dword 0 jz .vmgcm_00 call vm_get_cur_vert_rate mov eax,[0FE00h] mov ebx,[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 endf ; EBX=3 (in applications ECX=3)- Change Video Mode ; ; IN: ecx = VertRate*65536+VideoMode ; OUT: eax = 0 if no error ; func vm_set_video_mode begin cmp [mdrvm],dword 0 jz .vmsvm_00 call vm_set_selected_mode ; xor eax,eax retn .vmsvm_00: xor eax,eax dec eax retn endf ; EBX=4 (in applications ECX=4)- Return at Start System Video Mode ; ; IN: ; OUT: eax = = 0 if no error ; func vm_restore_init_video_mode begin cmp [mdrvm],dword 0 jz .vmrivm_00 call vm_restore_reg xor eax,eax retn .vmrivm_00: xor eax,eax dec eax retn endf ; 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 ; func vm_change_screen_size begin 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 endf ; 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 ; func vm_change_position_screen begin cmp [mdrvm],dword 0 jz .vmcps_00 ; ... xor eax,eax retn .vmcps_00: xor eax,eax dec eax retn endf ;-----Drivers Subfunctions--------- ; ; Searching i40 system functions pointer table in kernel area location ; func vm_search_sys_func_table begin 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,010000h ; Start address of kernel location lodsd mov edx,eax cld .vmssft_00: cmp esi,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 endf ; IN: ; OUT: eax= vertical rate in Hz func vm_get_cur_vert_rate begin 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,[0F600h] xor edx,edx div ebx inc eax mov [refrate],eax pop ebx pop edx retn endf func vm_calc_pixelclock begin 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 endf ; ; Safe of initial CRTC state ; func vm_safe_reg begin 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 endf ; ; Restore of initial CRTC state ; func vm_restore_reg begin push eax push ebx push edx push esi mov eax,[oldX] mov [0FE00h],eax mov eax,[oldY] mov [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 endf ; Calculate of possible vertical refrash rate ; (light version of function) func vm_calc_refrate begin 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 endf func vm_get_initial_videomode begin push eax mov eax,dword [0FE00h] mov [oldX],eax mov eax,dword [0FE04h] mov [oldY],eax mov eax,dword [0FE0Ch] ; initial video mode and ax,01FFh mov dword [initvm],eax pop eax retn endf ; IN: eax = 0/1 - -/+ 1 position of width func vm_inc_dec_width begin 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 endf ; ; Copy driver info to application area ; ; IN: ecx (in app. edx) - pointer to 512-bytes info area in application ; OUT: func vm_transfer_drv_info begin 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,[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 endf ; ; Set selected video mode ; (light version) ; ; IN: ecx = VertRate*65536+VideoMode ; func vm_set_selected_mode begin 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 [0FE00h],ecx mov [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 endf ;-[ mike.dld ]- begin --------------- include 'normal.asm' ;-[ mike.dld ]- end ----------------- ;------------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 ;-[ mike.dld ]- begin --------------- dd vm_mike_init ; dd vm_mike_cursor_pos dd vm_mike_uninit ;-[ mike.dld ]- end ----------------- ;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 align 4 ;-[ mike.dld ]- begin --------------- ;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 ;-[ mike.dld ]- end ----------------- 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: ;-[ mike.dld ]- begin --------------- align 4 include_debug_strings ;-[ mike.dld ]- end ----------------- DRVM_END: align 4 ;-[ mike.dld ]- begin --------------- oldX dd ? oldY dd ? initvm dd ? pclock dd ? ;-[ mike.dld ]- end ----------------- 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 ? ;-[ mike.dld ]- begin --------------- cnt dd ? align 16 tr RECT rct RECT ;rb 40*sizeof.RECT ;-[ mike.dld ]- end -----------------