;***************************************************************************** ;* .-= MOUSE PC1 Project =-. * ;* Int33h mouse hook for PC1 - NECV40 0.97 by Simone Riminucci (C) 2016 * ;* Started: 29.11.2016 * ;* Last updated 21.02.2017 * ;* Tested on: OLIVETTI PRODEST PC1 (NEC V40 XT, 512/640kB) * ;* * ;* Only 1904 byte Resident! * ;* Compile with NASM (186 code) * ;* Hardware Mouse pointer using YAMAHA V6335D special registers ! * ;***************************************************************************** CPU 186 ;code compatability ;%define DEBUG ;%define CALL_OLD_INT33 BIOS_DATA_SEG EQU 40h driverversion equ 303h ;imitated Microsoft driver version %include "constant.inc" ; Stuff that never changes. %macro TEST1 2 ;test 1 bit (n. CL). ZF is set if bit is zero. ; out CY=0 V=0, ZF as needed %ifn %2=CL %error "Only CL as second parameter" %endif db 0Fh %if %1=AL db 10h db 0C0h %elif %1=AX db 11h db 0C0h %else %error "Invalid Parameter" %endif %endmacro %macro SET1 2 ;set 1 bit (n. CL). if ZF is set the bit go to zero. %ifn %2=CL %error "Only CL as second parameter" %endif db 0Fh %if %1=AL db 14h db 0C0h %elif %1=AH db 14h db 0C4h %elif %1=AX db 15h db 0C0h %else %error "Invalid Parameter" %endif %endmacro ;************** Program header *************************************************** ORG 100h ;use if compiling .COM file jmp start cmdlineflags db 0 KeyStatus db 0 Old_INT08 dd 0 ;old INT Old_INT09 dd 0 ;old INT %ifdef CALL_OLD_INT33 Old_INT33 dd 0 ;old INT %endif Old_INT09_MONK dd 0 ;old INT Already_in_user db 0 Cursor_Flag db 0FFh MIN_HRange dw 0 MAX_HRange dw 639 MIN_VRange dw 0 MAX_VRange dw 199 Hor_Ratio dw 8 Vert_Ratio dw 8 X_Mult_Ratio dw 8 Y_Mult_Ratio dw 8 CenterX dw 15 CenterY dw 15 H_Mickey_Count dw 0 V_Mickey_Count dw 0 Max_speed_D2 dw 2 Max_Speed_D dw 35h Button_Status dw 0 LB_Count_press dw 0 LB_PosX_last_press dw 0 LB_PosY_last_press dw 0 LB_Count_releases dw 0 LB_PosX_last_release dw 0 LB_PosY_last_release dw 0 RB_Count_press dw 0 RB_PosX_last_press dw 0 RB_PosY_last_press dw 0 RB_Count_releases dw 0 RB_PosX_last_release dw 0 RB_PosY_last_release dw 0 shift_X_Pos db 1 shift_ratioX db 0 shift_ratioY db 0 MouseX_Sum dw 160 MouseY_Sum dw 100 Cursor_attribute db 0F0h Last_mask db 0 User_Event_Mask db 0 ; Changed: Cursor pos,left press, left rel, right press, right rel Event_Handler_Addr dd 63620000h ORG_AX dw 0 ORG_BX dw 0 ORG_CX dw 0 ORG_DX dw 0 ORG_DI dw 0 ORG_SI dw 0 ORG_ES dw 0 screenmask dw 0011111111111111b ; 0 dw 0001111111111111b ; 2 dw 0000111111111111b ; 4 dw 0000011111111111b ; 6 dw 0000001111111111b ; 8 dw 0000000111111111b ; 10 dw 0000000011111111b ; 12 dw 0000000001111111b ; 14 dw 0000000000111111b ; 16 dw 0000000000011111b ; 18 dw 0000000000001111b ; 20 dw 0000000011111111b ; 22 dw 0001000011111111b ; 24 dw 0111100001111111b ; 26 dw 1111100001111111b ; 28 dw 1111110001111111b ; 30 cursormask dw 0000000000000000b ; 0 dw 0100000000000000b ; 2 dw 0110000000000000b ; 4 dw 0111000000000000b ; 6 dw 0111100000000000b ; 8 dw 0111110000000000b ; 10 dw 0111111000000000b ; 12 dw 0111111100000000b ; 14 dw 0111111110000000b ; 16 dw 0111111111000000b ; 18 dw 0111111000000000b ; 20 dw 0100011000000000b ; 22 dw 0000011000000000b ; 24 dw 0000001100000000b ; 26 dw 0000001100000000b ; 28 dw 0000000000000000b ; 30 Int33_sub_index dw Fun_00 ; Reset/Query driver Presence dw Fun_01 ; Display Pointer dw Fun_02 ; Hide Pointer dw Fun_03 ; Query Position & Buttons dw Fun_04 ; Move Pointer dw Fun_05 ; Query Button Pressed count ; BX = 0 left button ; 1 right button ; ; ; on return: ; BX = count of button presses (0-32767), set to zero after call ; CX = horizontal position at last press ; DX = vertical position at last press ; AX = status: ; |F-8|7|6|5|4|3|2|1|0| Button Status ; | | | | | | | | `---- left button (1 = pressed) ; | | | | | | | `----- right button (1 = pressed) ; `------------------- unused dw Fun_06 ; Get Mouse Button Release Information ; ; BL=Button ; ; on return: ; BX = count of button releases (0-32767), set to zero after call ; CX = horizontal position at last release ; DX = vertical position at last release ; AX = status dw Fun_07 ; Set Horizontal range ; CX = minimum H pos ; DX = maximum H pos dw Fun_08 ; Set Vertical range ; CX = minimum V pos ; DX = maximum V pos dw Fun_09 ; Set graphic pointer shape ; BX = horizontal hot spot (-16 to 16) ; CX = vertical hot spot (-16 to 16) ; ES:DX = pointer to screen and cursor masks (16 byte bitmap) dw Fun_0A ; Set text pointer mask dw Fun_0B ; Query last motion distance dw Fun_0C ; Set Event Handler dw no_fun ; Enable Light Pen Emulation dw no_fun ; Disable Light Pen Emulation dw Fun_0F ; Set Pointer Speed ; CX= Horizontal Ratio ; DX= Vertical Ratio dw no_fun ; Set Exclusion Area dw Fun_11 ; GET NUMBER OF BUTTONS (special PC1 MOUSE procedure) dw no_fun dw Fun_13 ; Set max for Speed Doubling dw Fun_14 ; Exchange Event Handler INT_08: pusha push ds push cs ;variable segment! pop ds mov byte [Last_mask], 0 call read_M_delta_coord cmp bl, 00h ; Value 00h or FFh = WAS MOVED! jz go3 cmp byte [Cursor_Flag], 0 ; default -1 (FF) not visible ; visible=0 jnz go2 update_cur: cli mov dx, 3DDh mov al, 60h+80h ;sistemiamo solo lo sprite per ora... out dx, al inc dx mov ax, [MouseX_Sum] shr ax, 1 add ax, [CenterX] xchg al, ah out dx,al xchg al, ah out dx,al mov ax, [MouseY_Sum] add ax, [CenterY] xchg al, ah out dx,al xchg al, ah out dx,al sti cmp bl, 0Fh ;me lo posso permettere perchш ho eliminato MOV mem,imm e CMP mem,imm -> CMP reg,imm jz return_to_fun04 ;adjust_cursor was on-going go2: or byte [Last_mask], 1 ; signal cursor movement to mask push es call Call_User ; there is X or Y movement! pop es go3: pop ds popa jmp far [cs:Old_INT08] %macro CHECK_THRES 0 ;test for AX < [Max_speed_D2] in valore assoluto SENZA jump! (prima ce ne erano 2!!!) ; AX shifted if |AX| > [Max_speed_D2] - CX Corrupted - speed optimized push AX mov CX, AX SHR CX, 0Fh xor AX, CX sub AX, CX cmp ax, [Max_speed_D2] ;carry set if Below [Max_speed_D2] cmc ;set if Higher of [Max_speed_D2] xor cl, cl rcl cl, 1 ;cl=1 if carry set, 0 otherwise pop ax ;tiriamo fuori il valore originale shl ax, cl %endmacro read_M_delta_coord: ; (BL) lo uso come "was moved!" mov BL, 0 ; was moved = no mov al, 10h ; load CTRC register out 0D4h,al in al, 0D5h cmp al, 0 je rm2 ; non ш cambiata la "X" cbw ; Converts byte in AL to word Value in AX by extending sign of AL throughout register AH. neg ax ; negative! la X ш sepre negativa, non so perchш dec BX add [H_Mickey_Count], ax ;here the mickey are NOT doubled! CHECK_THRES mov CL, byte [shift_ratioX] ;shifting is better than IMUL/IDIV 50+34=84 Clock!!! shl ax, cl add ax, [MouseX_Sum] call Verify_in_HRange mov [MouseX_Sum], ax rm2: mov al, 11h ; load CTRC register out 0D4h,al in al, 0D5h cbw cmp ax, 0 je rm4 dec BX ; was moved = sь piљ corto ancora: 1 solo byte CHECK_THRES rm3: add [V_Mickey_Count], ax ;here the mickey are NOT shifted mov CL, byte [shift_ratioY] ;shifting is better than IMUL/IDIV 50+34=84 Clock!!! shl ax, cl add ax, [MouseY_Sum] call Verify_in_VRange mov [MouseY_Sum], ax return_to_fun04: ;sь ш pulcioso, si risparmia un'altro byte se ш meno lontano di 127 byte! rm4: ret ; NOTA: non uso pushf/popf perchш sono giр salvate da INT09 procedure INT_09bis: push ax call Has_been_pressed_a_Mkey or al, al jnz pressed pop ax jmp far [cs:Old_INT09_MONK] INT_09: push ax call Has_been_pressed_a_Mkey or al, al jz GoTo_OldInt pressed: pusha push es push ds push cs ;RIGHT SEGMENT FOR DATA pop ds ;mov bx, cs ;mov ds, bx ;mov es, bx mov ah, [KeyStatus] test al, 4 jnz short loc_DE6 test al, 80h jnz short loc_DE0 or ah, 2 jmp short loc_DF3 loc_DE0: and ah, 1 jmp short loc_DF3 loc_DE6: test al, 80h jnz short loc_DF0 or ah, 1 jmp short loc_DF3 loc_DF0: and ah, 2 loc_DF3: and ah, 3 mov [KeyStatus], ah mov al, ah mov byte [Last_mask], 0 call Update_keyCount call Call_User pop ds pop es popa pop ax ;pre-interrupt AX preserved! iret ; ФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФ GoTo_OldInt: pop ax jmp far [cs:Old_INT09] ; ллллллллллллллл S U B R O U T I N E ллллллллллллллллллллллллллллллллллллллл ;corrupt only AX! Has_been_pressed_a_Mkey: in al, 64h ; AT Keyboard controller 8042. and al, 0D0h jz short loc_1C2C xor ax, ax ret loc_1C2C: in al, 60h ; AT Keyboard controller 8042. mov ah, al cli mov al, 61h ; Ok, key processed! out 20h, al ; Interrupt controller, 8259A. sti mov al, ah no_fun: ret no_user_fun: retf ; ллллллллллллллл S U B R O U T I N E ллллллллллллллллллллллллллллллллллллллл Update_keyCount: ;AL= xxxxxLxR mov bx, [Button_Status] mov byte [Button_Status], al xor cx, cx ;azzeriamo CH CL - CH tiene i bit RRLL, CL il numero di shift da fare xor al, bl shr al, 1 ;tasto SX: Carry =1 se cambiato =0 se non cambiato rispetto al vecchio status rcr ch, 1 ;inseriamo questo valore nel byte, al primo posto (+ significativo) shr ah, 1 ; Carry =1 se Pressed =0 se released rcl cl, 1 ; Qui CL diventa 1 se il tasto ш pressed! shr ch, cl ; Se pressed ш il quarto bit da mettere a 1, quindi lo spingo ancora avanti tipo "01000000" ; finito con il tasto sinistro = CH="LL000000" mov cl, 0 shr ah, 1 ; Carry =1 se Pressed =0 se released cmc ; Toggles (inverts) the Carry Flag rcl cl, 1 ; Qui CL diventa 1 se il tasto ш released! shr ch, cl ; aggiungiamo uno zero se ш released -> "0LL0000", altrimenti invariato shr al, 1 ; tasto DX: Carry =1 se cambiato =0 se non cambiato rispetto al vecchio status rcr ch, 1 ; lo aggiungiamo al solito a sx: adesso abbiamo: "RLL00000" o "RRLL0000" xor cl, 1 ; Inverto CL: se era 0 diventa 1 e viceversa shr ch, cl ; quindi aggiungiamo uno zero se ш pressed -> "0RLL0000", altrimenti invariato shr ch, 4 ;adesso abbiamo in CH i 4 bit 0000RRLL mov dh, ch mov dl, ch shl dl, 1 ;DL ш pronto per andare in [last_mask] '000RRLL0' mov si, [MouseX_Sum] mov di, [MouseY_Sum] xor bx, bx mov cl, 4 ;4 passaggi LB_Press, LB_Release, RB_Press, RB_Release .next shr dh, 1 jc .updatePR .cont add bx, LB_Count_releases-LB_Count_press loop .next mov byte [Last_mask], dl ret .updatePR inc word [LB_Count_press+bx] mov word [LB_PosX_last_press+bx], si mov word [LB_PosY_last_press+bx], di jmp .cont ; ФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФ INT_33: %ifdef CALL_OLD_INT33 or ah, ah jnz call_old33_if_exist %endif sti call Call_Subfun end_int33: iret call_old33_if_exist: %ifdef CALL_OLD_INT33 cmp word [cs:Old_INT33+2], 0 jz end_int33 jmp far [cs:Old_INT33] %endif ; ФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФ Install_INT09_MONK: cli mov ax, 3509h int 21h ; DOS - 2+ - GET INTERRUPT VECTOR ; AL = interrupt number ; Return: ES:BX = value of interrupt vector mov word [Old_INT09_MONK], bx mov word [Old_INT09_MONK+2], es mov dx, INT_09bis ; Int 09 (BIS) Entry Point mov ax, 2509h int 21h ; DOS - SET INTERRUPT VECTOR ; AL = interrupt number ; DS:DX = new vector to be used for specified interrupt sti ret ; ФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФ ;check for INT_09 hook! Check_INT09_MONK: xor ax, ax mov es, ax mov ax, cs cmp word [ES:09h*4+2], ax ;check for int09 data segment je allok ;SEMPLIFICO: se non ш nel segmento la cambio altrimenti lascio stare! ;mov ax, 3509h ;int 21h ; DOS - 2+ - GET INTERRUPT VECTOR ; ; AL = interrupt number ; ; Return: ES:BX = value of interrupt vector ;mov ax, cs ;mov cx, es ;cmp ax, cx ;jne install_newint ;qualcuno (monkey?) ha cambiato l'int 09 ;mov cx, INT_09 ;cmp cx, bx ;je allok ;mov cx, INT_09bis ;cmp cx, bx ;je allok install_newint: call Install_INT09_MONK allok: ret ; ллллллллллллллл S U B R O U T I N E ллллллллллллллллллллллллллллллллллллллл Reset_pointer_and_var: xor ax, ax ;mov mem, ax ш piљ veloce e occupa meno di mov mem,0 mov bx, 8 ;per i valori da 8 mov word [MouseX_Sum], 320 mov word [MouseY_Sum], 100 mov word [Hor_Ratio], bx mov word [Vert_Ratio], bx mov byte [Already_in_user], al mov byte [User_Event_Mask], al mov word [Event_Handler_Addr+2], cs mov dx, no_user_fun mov word [Event_Handler_Addr], dx mov word [H_Mickey_Count], ax ; horizontal mickey count (-32768 to 32767) mov word [V_Mickey_Count], ax mov word [X_Mult_Ratio], bx mov word [Y_Mult_Ratio], bx mov byte [CenterX], 15 mov byte [CenterY], 15 mov byte [Max_speed_D2], 2 mov byte [Max_Speed_D], 35h mov word [MIN_VRange], ax mov word [MIN_HRange], ax mov BYTE [shift_X_Pos], al ;check for INT_09 hook! call Check_INT09_MONK mov ah, 0Fh int 10h ; - VIDEO - GET CURRENT VIDEO MODE ; Return: AH = number of columns on screen ; AL = current video mode ; BH = current active display page mov word [MAX_VRange], 199 mov word [MAX_HRange], 639 cmp al, 06h je cnt1 mov BYTE [shift_X_Pos], 1 cnt1: lea si, [screenmask] call Copy_cursor_shape ; Copy cursor addressed by DS:SI call TransMult ret ; ллллллллллллллл S U B R O U T I N E ллллллллллллллллллллллллллллллллллллллл ; Reset/Query driver Presence Fun_00: mov [Cursor_Flag], byte 0 call Fun_02 call Reset_pointer_and_var xor ax,ax mov byte [User_Event_Mask], al ; Changed: Cursor pos,left press, left rel, right press, right rel dec ax ;mov ax, 0FFFFh ;INSTALLED mov [ORG_AX], ax mov ax, 2 ;0FFFFh ;2 Buttons mov [ORG_BX], ax ret ; ллллллллллллллл S U B R O U T I N E ллллллллллллллллллллллллллллллллллллллл ; Display Pointer Fun_01 cmp byte [Cursor_Flag], 0 ; default -1 (FF) not visible ; visible=0 jz end_fun_01 ; giр visibile inc byte [Cursor_Flag] jnz end_fun_01 mov ah, byte [Cursor_attribute] mov al, 68h+80h out 0DDh,AX ;DD->AL DE->AH jmp adjust_cur end_fun_01: ret ; ллллллллллллллл S U B R O U T I N E ллллллллллллллллллллллллллллллллллллллл ; Hide Pointer Fun_02 dec byte [Cursor_Flag] ;cmp byte [Cursor_Flag], 0FFh ; default -1 (FF) not visible ; visible=0 ;jnz end_fun_02 ; always HIDE! mov al, 68h+80h mov ah, 0Fh ;cursor transparent out 0DDh,AX ;DD->AL DE->AH end_fun_02: ret ; ллллллллллллллл S U B R O U T I N E ллллллллллллллллллллллллллллллллллллллл ; Query Position & Buttons Fun_03: ;pushf ; out: ; CX = Horizontal (X) position ; DX = Vertical (Y) position ; BX = Button Status (bit 0-1=L-R) mov ax, [Button_Status] mov [ORG_BX], ax mov ax, [MouseX_Sum] mov [ORG_CX], ax mov ax, [MouseY_Sum] mov [ORG_DX], ax ;popf ;check for INT_09 hook! call Check_INT09_MONK ret ; ллллллллллллллл S U B R O U T I N E ллллллллллллллллллллллллллллллллллллллл ; Move Pointer Fun_04: mov ax, dx call Verify_in_VRange ; Verify if pointer in Vertical Range ; if not then move mov bx, ax mov ax, cx call Verify_in_HRange ; Verify if pointer in Horizontal Range ; if not then move mov [MouseX_Sum], ax mov [MouseY_Sum], bx cmp byte [Cursor_Flag], 0 ; default -1 (FF) not visible ; visible=0 jnz endfun4 adjust_cur mov BL, 0Fh ;usede to call/ret on update_cursor ^^ call update_cur endfun4: ret ; ллллллллллллллл S U B R O U T I N E ллллллллллллллллллллллллллллллллллллллл ; Query Button Pressed count ; BX = 0 left button ; 1 right button ; ; ; on return: ; BX = count of button presses (0-32767), set to zero after call ; CX = horizontal position at last press ; DX = vertical position at last press ; AX = status: ; |F-8|7|6|5|4|3|2|1|0| Button Status ; | | | | | | | | `---- left button (1 = pressed) ; | | | | | | | `----- right button (1 = pressed) ; `------------------- unused Fun_05: cmp bx, 1 ja Fun05_end jb Fun_05Out mov bx, RB_Count_press-LB_Count_press ;0=SX o delta=DX Fun_05Out: xor ax, ax xchg ax, [LB_Count_press+BX] ;cosь azzero anche COUNT con un'unica istruzione, veloce! mov [ORG_BX], ax mov ax, [LB_PosX_last_press+BX] mov [ORG_CX], ax mov ax, [LB_PosY_last_press+BX] mov [ORG_DX], ax mov ax, [Button_Status] mov [ORG_AX], ax Fun05_end: ret ; Get Mouse Button Release Information ; ; BL=Button ; ; on return: ; BX = count of button releases (0-32767), set to zero after call ; CX = horizontal position at last release ; DX = vertical position at last release ; AX = status Fun_06: cmp bx, 1 ja Fun05_end jb .phase2 ;se bx=0 don't add L/R offset mov bx, RB_Count_press-LB_Count_press .phase2 add bx, LB_Count_releases-LB_Count_press jmp Fun_05Out ; ллллллллллллллл S U B R O U T I N E ллллллллллллллллллллллллллллллллллллллл ; Set Horizontal range ; CX = minimum H pos ; DX = maximum H pos Fun_07: call Invert ; Invert CX/DX if necessary (DX also is some byte less (8 byte!) .ok: xchg ah,al out dx, al xchg ah,al out dx, al loop .copy_next ; Load Values ret ; ІІІІІІІІІІІІІІІ S U B R O U T I N E ІІІІІІІІІІІІІІІІІІІІІІІІІІІІІІІІІІІІІІІ ; Normally Set text pointer mask ; but in this special driver set the graphics cursor color attribute ; BX = FF , then CX = AND/XOR attribute. F0 = white/black not trasparent. ; DX = 1 -> blink Fun_0A: cmp bl, 0FFh jnz endfun mov byte [Cursor_attribute], cl mov al, 64h+80h ;register 64h out 0DDh, al xchg al, dl or al, 110b ;set mask/and/xor = ON out 0DEh, al dec byte [Cursor_Flag] jmp Fun_01 ;endfun0A: ret ; ллллллллллллллл S U B R O U T I N E ллллллллллллллллллллллллллллллллллллллл ; Query last motion distance Fun_0B: ;pushf cli xor ax, ax ;cosь azzeriamo in un passaggio solo! xchg ax, [H_Mickey_Count] ; horizontal mickey count (-32768 to 32767) mov [ORG_CX], ax xor ax, ax xchg ax, [V_Mickey_Count] ; vertical mickey count (-32768 to 32767) mov [ORG_DX], ax ;popf endfun: ret ; ллллллллллллллл S U B R O U T I N E ллллллллллллллллллллллллллллллллллллллл ; Set Event Handler Fun_0C: ;pushf cli mov word [Event_Handler_Addr], dx mov dx, [ORG_ES] mov word [Event_Handler_Addr+2], dx and cl, 7Fh ; exclude high bit (7) mov byte [User_Event_Mask], cl ; Changed: Cursor pos,left press, left rel, right press, right rel ;popf sti ret ;Fun_0D: ret ;Fun_0E: ret ; ІІІІІІІІІІІІІІІ S U B R O U T I N E ІІІІІІІІІІІІІІІІІІІІІІІІІІІІІІІІІІІІІІІ ; Set Pointer Speed ; CX= Horizontal Ratio ; DX= Vertical Ratio Fun_0F: ;cmp cx,0 ;je EndFun10 ;una divisione per /0 avrebbe esiti funesti! ;cmp dx,0 ;je EndFun10 ;mov [Hor_Ratio], cx ;mov [Vert_Ratio], dx xchg ax, cx ;se porto tutto su AX risparmio 1 byte ogni operazione! cmp ax, word 0000h je .skipHor ;una divisione per /0 avrebbe esiti funesti! mov [Hor_Ratio], ax .skipHor xchg ax, dx cmp ax, word 0000h ;una divisione per /0 avrebbe esiti funesti! je EndFun ;pulcioso, ma risparmio 1 byte mov [Vert_Ratio], ax jmp TransMult ;Fun_10: ret ; ІІІІІІІІІІІІІІІ S U B R O U T I N E ІІІІІІІІІІІІІІІІІІІІІІІІІІІІІІІІІІІІІІІ ; Get driver type ; return_ AX= 33h Fun_11: mov ax, 33h ;Special PC1 mouse driver mov [ORG_AX], ax mov al, 2 mov [ORG_BX], ax ;number of buttons EndFun: ret ;Fun_12: ret ; ІІІІІІІІІІІІІІІ S U B R O U T I N E ІІІІІІІІІІІІІІІІІІІІІІІІІІІІІІІІІІІІІІІ ; Set max for Speed Doubling Fun_13: xchg ax, dx mov [Max_Speed_D], ax add ax, 11h mov bx, 23h xor dx, dx div bx mov [Max_speed_D2], ax ret ; ллллллллллллллл S U B R O U T I N E ллллллллллллллллллллллллллллллллллллллл ; Exchange Event Handler Fun_14: ;pushf cli mov ax, word [Event_Handler_Addr] mov [ORG_DX], ax mov word [Event_Handler_Addr], dx mov dx, [ORG_ES] mov ax, word [Event_Handler_Addr+2] mov [ORG_ES], ax mov word [Event_Handler_Addr+2], dx xor ax, ax mov al, byte [User_Event_Mask] ; Changed: Cursor pos,left press, left rel, right press, right rel mov [ORG_CX], ax and cl, 7Fh mov byte [User_Event_Mask], cl ; Changed: Cursor pos,left press, left rel, right press, right rel sti ;popf EndFun14: ret ;Fun_15: ret ;Fun_16: ret ;Fun_17: ret ;Fun_18: ret ;Fun_19: ret ; ІІІІІІІІІІІІІІІ S U B R O U T I N E ІІІІІІІІІІІІІІІІІІІІІІІІІІІІІІІІІІІІІІІ ; Transform multiplier in SHIFT-LEFT ; me ne sbatto dei risultati che hanno un rapporto Mult/Ratio < 1 anche perchш il mouse ш giр lento cosь di suo ; [shift_X_Pos] giр considerato! TransMult: mov al, byte [shift_X_Pos] ;parto da questo valore mov byte [shift_ratioX], al mov ax, [X_Mult_Ratio] xor dx, dx div word [Hor_Ratio] .redo1: shr AX, 1 cmp ax, 0 je .ok1 inc byte [shift_ratioX] jmp .redo1 .ok1: mov byte [shift_ratioY], 0 mov ax, [Y_Mult_Ratio] xor dx, dx div word [Vert_Ratio] .redo2: shr AX, 1 cmp ax, 0 je EndFun14 ;.ok2 - pulcioso ma risparmio! inc byte [shift_ratioY] jmp .redo2 ;.ok2: ret ; ІІІІІІІІІІІІІІІ S U B R O U T I N E ІІІІІІІІІІІІІІІІІІІІІІІІІІІІІІІІІІІІІІІ ; Set mouse sensivity ; BX = horizontal coordinates per pixel ; CX = vertical coordinates per pixel ; DX = double speed threshold Fun_1A: shr bx, 2 mov [X_Mult_Ratio], bx shr cx, 2 mov [Y_Mult_Ratio], cx call TransMult jmp Fun_13 ; Set max for Speed Doubling ; ІІІІІІІІІІІІІІІ S U B R O U T I N E ІІІІІІІІІІІІІІІІІІІІІІІІІІІІІІІІІІІІІІІ ;adjust_mult: mov bl, 0Ah ; div bl ; xor ah, ah ; cmp al, 0Ah ; jbe short loc_B9B ; mov al, 0Ah ;loc_B9B: mov bx, moltiplic ; ;add bx, ax ; ;mov al, [bx] ;qui uso XLAT = mov al, [BX+AL] ; XLAT ; ret ; --------------------------------------------------------------------------- ;moltiplic db 1, 2, 3, 4, 6, 8, 0Ah, 0Eh, 12h, 16h, 1Eh ; ІІІІІІІІІІІІІІІ S U B R O U T I N E ІІІІІІІІІІІІІІІІІІІІІІІІІІІІІІІІІІІІІІІ ; Query Mouse Sensivity Fun_1B: ;mov ax, [Hor_CoordXPixel] mov ax, [X_Mult_Ratio] shl ax, 2 mov [ORG_BX], ax ;mov ax, [Ver_CoordXPixel] mov ax, [Y_Mult_Ratio] shl ax, 2 mov [ORG_CX], ax mov ax, [Max_Speed_D] mov [ORG_DX], ax ret ;Fun_1C: ret ;Fun_1D: mov [CRT_page_num], bx ; ret ;Fun_1E: mov ax, [CRT_page_num] ; mov [ORG_BX], ax ; ret ;Fun_1F: ret ;Fun_20: ret ;Fun_21: ret ;Fun_22: ret ; LANGUAGE = ITA!!! :) Fun_23: mov word [ORG_BX], 08h ret ; 24 - Get software version, mouse type and IRQ ; Out: [AX] = 24h/FFFFh (installed/error) ; [BX] (version) ; [CL] (IRQ #/0=PS/2) ; [CH] = 1=bus/2=serial/3=InPort/4=PS2/5=HP (mouse type) ; Use: driverversion Fun_24: mov word [ORG_BX], driverversion mov word [ORG_CX], 0309h ;inport, IRQ=09 ret ; ллллллллллллллл S U B R O U T I N E ллллллллллллллллллллллллллллллллллллллл ; Call INT 33 subfunction in AX Call_Subfun: push bp push ds push cs ;right segment! pop ds mov [ORG_AX], ax mov [ORG_BX], bx mov [ORG_CX], cx mov [ORG_DX], dx mov [ORG_DI], di mov [ORG_SI], si mov [ORG_ES], es push ds pop es cmp ax, 14h ja short OtherFuns ; other functions! push si mov si, ax shl si, 1 mov ax, [Int33_sub_index+si] pop si call_it: call ax jmp short loc_6F5 ; ФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФФ ; 2A - Get cursor hot spot ; Out: [AX] (cursor visibility counter) ; [BX] (hot spot X) ; [CX] (hot spot Y) ; [DX] = 1=bus/2=serial/3=InPort/4=PS2/5=HP (mouse type) ; cmp al, 2Ah ; jnz short Fun_4D ; mov ax, [Cursor_Flag] ; mov [ORG_AX], AX ; mov ax, 16 ; sub ax, [CenterX] ; mov [ORG_BX], AX ; mov ax, 16 ; sub ax, [CenterY] ; mov [ORG_CX], AX ; mov word [ORG_DX], 3 ;inport mouse ; jmp short loc_6F5 Fun_4D: ; Pointer to Microsoft Label! mov word [ORG_DI], Copyright1983 mov [ORG_ES], cs ret Fun_6D: jnz short loc_6F5 mov [ORG_DI], word magicnumber ;word 204h mov [ORG_ES], cs ret execute: shl bx,1 call [CS:other_address+bX] jmp short loc_6F5 OtherFuns: mov bx, 4 more: cmp al, [other_num+bx] jz execute dec bx jnz more loc_6F5: mov ax, [ORG_ES] mov es, ax mov si, [ORG_SI] mov di, [ORG_DI] mov dx, [ORG_DX] mov cx, [ORG_CX] mov bx, [ORG_BX] mov ax, [ORG_AX] pop ds pop bp ret other_address: dw Fun_1A, Fun_1B, Fun_23, Fun_24, Fun_4D, Fun_6D other_num db 1Ah, 1Bh, 23h, 24h, 4Dh, 6Dh ; ллллллллллллллл S U B R O U T I N E ллллллллллллллллллллллллллллллллллллллл Call_User: cmp byte [Already_in_user], 0FFh jz endend mov byte [Already_in_user], 0FFh xor ax,ax mov al, byte [Last_mask] and al, byte [User_Event_Mask] ; Changed: Cursor pos,left press, left rel, right press, right rel mov bp, Event_Handler_Addr ; Custom Event Handler jz no_sub call CALL_FUN_AT_BP ; call function (save all registers) ; @ BasePointer no_sub: mov byte [Already_in_user], 0 endend: ret ; ллллллллллллллл S U B R O U T I N E ллллллллллллллллллллллллллллллллллллллл ; call function (save all registers) ; @ BasePointer CALL_FUN_AT_BP: mov bx, [Button_Status] mov cx, [MouseX_Sum] mov dx, [MouseY_Sum] mov si, word [H_Mickey_Count] ; horizontal mickey count (-32768 to 32767) mov di, word [V_Mickey_Count] ; vertical mickey count (-32768 to 32767) ;pushf sti call far [cs:bp] ;popf PUSH CS ;return to my DS segment POP DS ret ; ІІІІІІІІІІІІІІІ S U B R O U T I N E ІІІІІІІІІІІІІІІІІІІІІІІІІІІІІІІІІІІІІІІ ; Invert CX/DX if necessary (DXForced!"... mov ah, 9 int 21h ; DOS - PRINT STRING %endif cont0: cli call set_mouse_keyb ; Set keyboard chip 8042 ; to respond to mouse click -> scancode ; Left Button 77h ; Middle Button 78h ; Right Button 79h or al, al %ifndef DEBUG jz short print_mouse_non_connesso %endif call Install_INT08 call Install_INT09 call Install_INT33 call reset_V6355D call Reset_pointer_and_var test byte [cmdlineflags], showcurs jz skipshow call Fun_01 skipshow: STI terminate_but_stay_resident: cont3: mov ah, 51h ;Get application's PSP address int 21h ;we get it in bx mov es, bx mov es, [es:2Ch] ;Get address of environment block. mov ah, 49h ;DOS deallocate block call. int 21h ;get rid of PSP! mov dx, notresident ; only resident part will be saved mov cl, 4 shr dx, cl ; paragraph to keep inc dx ; 1 paragraph more... safer for roundings MOV AX, 3100h ; INT 21h ;stay resident and exit terminate: lea dx, [already] ; "Giр installato!"... mov ah, 9 int 21h ; DOS - PRINT STRING error: MOV AX, 4C01h ;AH 4C = Exit to DOS, ERRORLEVEL AL 01 INT 21h print_mouse_non_connesso: lea dx, [aSpiacentiIlMou] ; "Non connesso!"... mov ah, 9 int 21h ; DOS - PRINT STRING MOV AX, 4C02h ;AH 4C = Exit to DOS, ERRORLEVEL AL 02 INT 21h reset_V6355D: cli ;mov dx, 3DDh ;mov al, 65h+80h ;out dx, al ;inc dx ;mov al, 89h ;mouse enable ;out dx, al push ds mov bx, [Equipment_Addr] mov ax, BIOS_DATA_SEG mov ds, ax mov al, [bx] pop ds test byte [cmdlineflags], forceEGA jnz .force test al, 1 jz .cont .force and al, 0FEh ; azzera l'ultimo bit ;;;;mov [bx], al ; lo riscrivo indietro in modo che non venga piљ cambiato!?!? or byte [cmdlineflags], forceEGA ; mi segno che era quello! out 68h, al ; cosь "accende" lo schermo V6355D e il counter del mouse in al, 0D1h cmp al, 0FFh ; questo controllo ш utile solo per computer non-pc1 jnz .wmsg test byte [cmdlineflags], nocheck jz not_PC1 .wmsg lea dx, [EGAVGA] ; "EGA/VGA Patch installed"... mov ah, 9 int 21h ; DOS - PRINT STRING .cont mov dx, 3DDh mov al, 64h+80h out dx, al inc dx mov al, 6h ;mouse AND & XOR enable out dx, al sti ret check_for_PC1: PC1_Equipment_Addr EQU 89h PC1HD_Equipment_Addr EQU 0A1h push bx push ds mov ax, 0F000h mov ds, ax mov bx, 0FFFDh ; penultimi due byte del BIOS mov ax, [bx] pop ds mov bl, PC1HD_Equipment_Addr cmp ax, 0FE44h ; PC1 - Floppy jz short pc1dd cmp ax, 0FE49h ; PC1 - Unknown jz short loc_2B1C cmp ax, 0FE4Ah ; PC1 - HD jnz short loc_2B22 pc1dd: mov bl, PC1_Equipment_Addr loc_2B1C: mov ax, 0FFh jmp short loc_2B25 loc_2B22: mov ax, 0 loc_2B25: mov [Equipment_Addr],bl pop bx ret not_PC1: lea dx, [SiamoSpiacenti] ; "Siamo spiacenti di non poter installare"... mov ah, 9 int 21h ; DOS - PRINT STRING ; DS:DX -> string terminated by "$" jmp error Value_for_8042 db 12h, 77h, 78h, 79h, 1 ;valori dei tre tasti del mouse: 77h 78h 79h set_mouse_keyb: cli mov al, 12h push ax mov dx, 64h wait_8042: in al, dx ; AT Keyboard controller 8042. and al, 2 jnz short wait_8042 pop ax out dx, al ; AT Keyboard controller 8042. wait_8042f: in al, 64h ; AT Keyboard controller 8042. and al, 1 jz short wait_8042f in al, 60h ; AT Keyboard controller 8042. and al, 1 jnz short skip push si lea si, [Value_for_8042] mov cx, 5 cld load_next: lodsb ; Load Value: 12h 77h 78h 79h 01 push ax mov dx, 64h wait_8042g: in al, dx ; AT Keyboard controller 8042. and al, 2 jnz short wait_8042g pop ax mov dx, 60h out dx, al ; AT Keyboard controller 8042. loop load_next ; Load Value: 12h 77h 78h 79h 01 mov ax, 0FFh pop si sti ret skip: xor ax, ax sti ret ;=========================================================================== ;Procedure: ucase ;Purpose: Converts character in AL to uppercase. ; ;Input: AL=character ; ;Output: AL=uppercase character (if a-z) ; All other registers preserved. (flags too) ; ;Processing: test valid range (a-z), set to upper, exit ;--------------------------------------------------------------------------- ucase: pushf cmp al,"a" ;if it's not a-z, skipit jb noupper cmp al,"z" ja noupper and al,5fh ;strip off a few bits to make it upper noupper: popf ret ;##################### start cmd line interpret #################### ; command line flags help EQU BIT0 ; help requested nocheck EQU BIT1 ; don't check for PC1 showcurs EQU BIT2 ; show cursor at loading forceinst EQU BIT3 ; forced install over an existing driver forceEGA EQU BIT4 ; force EGA/VGA book debug EQU BIT5 ; debug bit koverride EQU BIT5 ; debug bit writeprotect EQU BIT6 ; write protected bit noint10 EQU BIT7 ; light INT10 hook (composit) process_cmdline: push ds push bx push si mov ah, 51h int 21h mov ds, bx mov cx, bx mov si, 80h mov bh, 0 mov bl, byte [si] add si, bx inc si mov byte [si], NULL ;zero terminate mov si, 81h cmdlineloop: mov ds,cx lodsb ;Transfers string element addressed by DS:SI to the accumulator push cs pop ds cmp al, " " ; found a space? jz cmdlineloop cmp al, NULL ; found end of line? jz exitpc cmp al, "-" ; found a flag? jz checkflags cmp al, "/" ; found a flag? jz checkflags ; unknow skip but show help or byte [cmdlineflags], help jmp cmdlineloop exitpc: pop si pop bx pop ds ret checkflags: mov ds,cx lodsb ;Transfers string element addressed by DS:SI to the accumulator push cs pop ds cmp al, " " ; false flag jz cmdlineloop cmp al, NULL ; found end of line? jz exitpc cmp al, "-" ; found a double flag? jz checkflags cmp al, "/" ; found a double flag? jz checkflags ; must be a flag call ucase cmp al, "?" jz sethelp cmp al, "H" jz sethelp cmp al, "I" jz setignorenotPC1 cmp al, "M" jz setshowcursor cmp al, "F" jz setforceinst cmp al, "E" jz setforceEGA jmp cmdlineloop ; nothing we care about, continue ; could jump to help msg sethelp: or byte [cmdlineflags], help jmp checkflags ; allows flags to be stacked setignorenotPC1: or byte [cmdlineflags], nocheck jmp checkflags ; allows flags to be stacked setshowcursor: or byte [cmdlineflags], showcurs jmp checkflags ; allows flags to be stacked setforceinst: or byte [cmdlineflags], forceinst jmp checkflags ; allows flags to be stacked setforceEGA: or byte [cmdlineflags], forceEGA jmp checkflags ; allows flags to be stacked ;##################### end cmd line interpret #################### Install_INT08: cli mov ax, 3508h int 21h ; DOS - 2+ - GET INTERRUPT VECTOR ; AL = interrupt number ; Return: ES:BX = value of interrupt vector mov word [Old_INT08], bx mov word [Old_INT08+2], es mov dx, INT_08 ; Int 08 Entry Point mov ax, 2508h int 21h ; DOS - SET INTERRUPT VECTOR ; AL = interrupt number ; DS:DX = new vector to be used for specified interrupt sti ret Install_INT09: cli mov ax, 3509h int 21h ; DOS - 2+ - GET INTERRUPT VECTOR ; AL = interrupt number ; Return: ES:BX = value of interrupt vector mov word [Old_INT09], bx mov word [Old_INT09+2], es mov dx, INT_09 ; Int 09 Entry Point mov ax, 2509h int 21h ; DOS - SET INTERRUPT VECTOR ; AL = interrupt number ; DS:DX = new vector to be used for specified interrupt sti ret Install_INT33: cli %ifdef CALL_OLD_INT33 push ds xor ax, ax mov ds, ax mov si, 0CCh mov bx, [si] mov cx, [si+2] pop ds mov [Old_INT33], bx mov [Old_INT33+2], cx %endif lea dx, [INT_33] ; Int33 Entry Point mov al, 33h mov ah, 25h ; DOS - SET INTERRUPT VECTOR int 21h ; AL = interrupt number ret ; DS:DX = new vector to be used for specified interrupt display_help: mov ah, 9 lea dx, [helpmsg] ; display help message int 21h exit mov ax, 4c02h ; end int 21h END: