;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ ;Input Module ; Copyright (C)2000 Alpha-II Productions ;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ .MODEL MEDIUM .386 LOCALS CODEMAIN SEGMENT PUBLIC "CODE" PAGE USE16 CODEMAIN ENDS DATAMAIN SEGMENT PUBLIC "DATA" PAGE USE16 DATAMAIN ENDS INCLUDE Input.Inc ;INCLUDE CMov.Inc ;INCLUDE MMX.Inc INCLUDE Video.Inc ;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ DATAMAIN SEGMENT ;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ ;Directives ;MSPos LABEL NEAR ;Uncomment to use mouse driver for cursor positioning ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ ;Equates ;Keyboard K_PRESS = 10h ;A key was pressed K_REL = 20h ;A key was released K_CHAR = 40h ;A non-option/switch key was pressed ;Mouse M_MAXX = 720 ;Right X boundary for mouse cursor M_MAXY = 480 ;Bottom Y boundary for mouse cursor M_NEW = 01h ;Cursor is new, don't replace underlying screen M_EVENT = 02h ;An event is being handled M_VIS = 04h ;Cursor is visible M_BLOCK = 08h M_ABS = 10h ;Cursor has moved M_CHAR = 20h ;Cursor has moved to a new character ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ ;Data ;The corresponding ASCII value to a scan code from the keyboard KeyLower DB 0,208,'1','2','3','4','5','6','7','8','9','0','[',']',203,204 DB "'",',','.','p','y','f','g','c','r','l','/','=',202, 0,'a','o' DB 'e','u','i','d','h','t','n','s','-','`', 0,'\',';','q','j','k' DB 'x','b','m','w','v','z', 0,'*', 0,' ', 0,209,210,211,212,213 DB 214,215,216,217,218, 0, 0,198,194,200,'-',196,'5',197,'+',199 DB 195,201,192,193,205, 0,'\',219,220, 0, 0,221,222,223, 0, 0 ;ASCII value if the shift key is being held KeyUpper DB 0,208,'!','@','#','$','%','^','&','*','(',')','{','}',203,204 DB '"','<','>','P','Y','F','G','C','R','L','?','+',202, 0,'A','O' DB 'E','U','I','D','H','T','N','S','_','~', 0,'|',':','Q','J','K' DB 'X','B','M','W','V','Z', 0,'*', 0,' ', 0,209,210,211,212,213 DB 214,215,216,217,218, 0, 0,198,194,200,'-',196,'5',197,'+',199 DB 195,201,192,193,205, 0,'|',219,220, 0, 0,221,222,223, 0, 0 ;ASCII value if key has no equivilant ;(If bits 7&6 of the ASCII value is set, then lower 6 bits are index to table) ;Ins Del Up Dn Lf Rt Hm End PUp PDn CR BS Tab Sys KeyExtnd DB 16, 17, 24, 25, 27, 26, 18, 23, 30, 31, 13, 8, 9,240, 0, 0 DB 1,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255 ;Esc F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 ;Keys when NumLock is on DB '0','.','8','2','4','6','7','1','9','3' ALIGN 32 ;Max cursor size is 9x16 CurMask DW 7 DUP(-1) ;DUPs provide padding for vertical movement DW 1111111111111111b DW 1111111111111111b DW 1011111111111111b DW 1001111111111111b DW 1000111111111111b DW 1000011111111111b DW 1000001111111111b DW 1000000111111111b DW 1000011111111111b DW 1010011111111111b DW 1111001111111111b DW 1111001111111111b DW 1111100111111111b DW 1111100111111111b DW 1111111111111111b DW 1111111111111111b DW 9 DUP(-1) CurBlack DW 7 DUP(0) DW 1000000000000000b DW 1100000000000000b DW 1010000000000000b DW 1001000000000000b DW 1000100000000000b DW 1000010000000000b DW 1000001000000000b DW 1000000100000000b DW 1000011110000000b DW 1010010000000000b DW 1101001000000000b DW 1001001000000000b DW 0000100100000000b DW 0000100100000000b DW 0000011000000000b DW 0000000000000000b DW 9 DUP(0) IFDEF MMX MMX_LBM DQ 00FF00FF00FF00FFh ;Lower Byte Mask - Use to erase hi-byte in packed words DQ ? DQ ? DQ ? MMXState DB 96 DUP(?) ENDIF KeyList DW ?,? RatList DW ?,? OldInt9 DD ? ;Old far pointer in int 9 OldInt33 DD ? ;Old far pointer to alternate mouse handler (if any) KeyPress LABEL WORD KeyASCII DB 0 ;ASCII code of key pressed KeyOpt DB 0 ;Flags corresponding to option keys KeyCode LABEL WORD KeyScan DB 0 ;Keyboard scan code KeyFlag DB 0 ;Flags for switch keys CharSet DW ?,? ;Near pointer the 512 character set MHide DB 0 ;Number of times the mouse has been turned off MStatus DB ? RatENum DB 0 ;Number of events that can be triggered by mouse KeyENum DB ? ;Number of events that can be triggered by keyboard RatX DB ? ;Character position of cursor RatY DB ? RatB DB ? ;Buttons currently being pressed RatBLast DB 0 ;Buttons that were being pressed MickeyX DW ? ;Number of mickeys (pixels) moved since last interrupt MickeyY DW ? AbsPosX DW ? ;Position of on screen cursor (in pixels) AbsPosY DW ? WinPos DW ? ;Window postion in video memory ChrPos DW ? ;Absolute index of current character position ChrScr DW 2*3 DUP(?) ;Charcters that were under the cursor DATAMAIN ENDS ;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ CODEMAIN SEGMENT ASSUME CS:CODEMAIN,DS:DATAMAIN ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ ;Keyboard Interrupt Handler ; ;Desc: ; Interrupt 9 (IRQ 1) is captured and replaced with this procedure. ; This routine supports 105-key (Windoze) keyboards, but not 122-key keyboards. ;In: ; nothing ;Out: ; KeyASCII = ASCII value of keypress, or code if not a character ; KeyScan = Scan code corresponding to value in KeyASCII (see table below) ; KeyOpt = Flags for various keys ; KeyFlag = Flags for switch keys and other stuff ;Destroys: ; nothing ; ;Scan codes: ; 00h N/A 20h D 40h F6 60h -- ; 01h Esc 21h F 41h F7 61h -- ; 02h 1 ! 22h G 42h F8 62h ; 03h 2 @ 23h H 43h F9 63h F16 ; 04h 3 # 24h J 44h F10 64h F17 ; 05h 4 $ 25h K 45h Num Lock 65h F18 ; 06h 5 % 26h L 46h Scroll Lock 66h F19 ; 07h 6 ^ 27h ; : 47h Home 7 67h F20 ; 08h 7 & 28h ' " 48h Up 8 68h F21 ; 09h 8 * 29h ` ~ 49h PgUp 9 69h F22 ; 0Ah 9 ( 2Ah Shift (L) 4Ah - 6Ah F23 ; 0Bh 0 ) 2Bh \ | (R) 4Bh Left 4 6Bh F24 ; 0Ch - _ 2Ch Z 4Ch 5 6Ch -- ; 0Dh = + 2Dh X 4Dh Right 6 6Dh EraseEOF ; 0Eh Backspace 2Eh C 4Eh + 6Eh ; 0Fh Tab 2Fh V 4Fh End 1 6Fh Copy/Play ; 10h Q 30h B 50h Down 2 70h ; 11h W 31h N 51h PgDn 3 71h ; 12h E 32h M 52h Insert 0 72h CrSel ; 13h R 33h , < 53h Delete . 73h ; 14h T 34h . > 54h SysRq* 74h ExSel ; 15h Y 35h / ? 55h 75h -- ; 16h U 36h Shift (R) 56h \ | (L) 76h Clear ; 17h I 37h * 57h F11 77h ; 18h O 38h Alt 58h F12 E0h Ext. key prefix ; 19h P 39h SpaceBar 59h E1h Ext. key prefix ; 1Ah [ { 3Ah CapsLock 5Ah PA1 FAh ACK ; 1Bh ] } 3Bh F1 5Bh F13 Window (L) FBh ; 1Ch Enter 3Ch F2 5Ch F14 Window (R) FCh ; 1Dh Ctrl 3Dh F3 5Dh F15 Menu FDh ; 1Eh A 3Eh F4 5Eh FEh RESEND ; 1Fh S 3Fh F5 5Fh FFh kbd error ; ; * Scan code 54h is only returned when Alt-PrintScr is pressed. Pressing PrintScr by itself has ; the same effect as Ctrl-*. Pressing the Pause key has the same effect as Ctrl-NumLock, except ; E1 is given as a prefix instead of E0. Ctrl-Pause (Break) is the same as Ctrl-ScrollLock. ; Understand? Neither do I. ALIGN 16 KeyInt9 PROC FAR Push DS EAX EBX ;Push used registers Mov AX,DATAMAIN Mov DS,AX In AL,60h ;Get scan code we were interrupted for Cmp AL,0E0h ;Is the key an extended keypress? JNE Short @@NotEnh ; No, Continue Or KeyFlag,K_EXT ;Set flag Mov AL,20h ;Acknowledge interrupt Out 20h,AL Pop EBX EAX DS IRet @@NotEnh: Test AL,80h ;Is it a key release or prefix? JZ @@KeyPress ; Nope, Jump to keypress Cmp AL,0B8h ;Was the Alt key released? JE Short @@AltRel ; Yep, Erase flag Cmp AL,9Dh ;Was the Ctrl key released? JE Short @@CtrlRel ; Yep Cmp AL,0AAh ;Was the left Shift key released? JE Short @@LShiftRel ; Yes Cmp AL,0B6h ;Was the right Shift key released? JE Short @@RShiftRel ; Yes Cmp AL,0BAh JE Short @@CapsRel Cmp AL,0C5h JE Short @@NumRel Cmp AL,0C6h JE Short @@ScrollRel Jmp @@GotKey @@RShiftRel: And KeyOpt,Not K_SHIFTR Jmp @@GotKey @@LShiftRel: And KeyOpt,Not K_SHIFTL Jmp @@GotKey @@CtrlRel: Test KeyFlag,K_EXT SetZ AL Dec AL And AL,K_CTRLL-K_CTRLR Add AL,K_CTRLR Not AL And KeyOpt,AL Jmp @@GotKey @@AltRel: Test KeyFlag,K_EXT SetZ AL Dec AL And AL,K_ALTL-K_ALTR Add AL,K_ALTR Not AL And KeyOpt,AL Jmp @@GotKey @@NumRel: XOr KeyFlag,K_NUMLCK Jmp Short @@SetLED @@ScrollRel: XOr KeyFlag,K_SCRLCK Jmp Short @@SetLED @@CapsRel: XOr KeyFlag,K_CAPLCK @@SetLED: @@KBWait1: In AL,64h Test AL,2 ;Are we clear to write data to the keyboard? JNZ Short @@KBWait1 ; Nope, Loop until we are Mov AL,0EDh ;EDh - Enable/Disable keyboard LED Out 60h,AL ;Write register index @@KBWait2: ;Wait for go ahead on write... In AL,64h Test AL,2 JNZ Short @@KBWait2 Mov AL,KeyFlag ;Write LED status (1=on) And AL,7 ;Lower three bits only Out 60h,AL Jmp @@GotKey @@KeyPress: Cmp AL,5Eh ;Was keypress an exetended key from a 122-key keyboard? JA @@GotKey ; Yup, Quit 'cause I don't care about it Or KeyFlag,K_PRESS ;A key (any key) was pressed Cmp AL,2Ah JE @@LShift Cmp AL,36h JE @@RShift Cmp AL,1Dh JE @@Ctrl Cmp AL,38h JE @@Alt Cmp AL,3Ah JE @@GotKey Cmp AL,45h JE @@GotKey Cmp AL,46h JE @@GotKey Or KeyFlag,K_CHAR ;An key corresponding to an ASCII char or function Mov KeyScan,AL Mov BX,Offset[KeyUpper] Test KeyOpt,K_SHIFT JNZ Short @@Upper Mov BX,Offset[KeyLower] @@Upper: XLAT And KeyOpt,Not K_ENH Mov AH,0C0h And AH,AL Cmp AH,0C0h ;Is the keypress an enhanced key? JNE Short @@NotExtnd ; Nope And AL,3Fh ;Isolate index Test KeyFlag,K_EXT ;Is key not an extended one? (ie number pad) SetNZ BL ; No Cmp AL,10 ;Is key on number pad? SetA BH ; No Or BH,BL Test KeyFlag,K_NUMLCK ;Is the num lock turned on? SetZ BL ; No Or BL,BH Dec BH ;BH = (!K_EXT)&&(KeyExtnd<=10) Dec BL ;BL = (!K_EXT)&&(KeyExtnd<=10)&&(K_NUM) Mov AH,BL ;AH = !BL Not AH And BH,K_NPAD ;Set number pad flag And AH,K_ENH ;Set enhanced key flag Or AH,BH Or KeyOpt,AH Mov BX,Offset[KeyExtnd] ;Get key XLAT Or KeyOpt,K_ENH Jmp Short @@CapsOff @@NotExtnd: Test KeyFlag,K_CAPLCK ;Is the CapsLock turned on? JZ Short @@CapsOff ; No, Save character Test AL,64 ;Could character be a letter? JZ Short @@CapsOff ; No, Quit Mov AH,31 And AH,AL ;Is character less than 'A'? JZ Short @@CapsOff ; Yes, Quit Cmp AH,90 ;Is character a letter? JA Short @@CapsOff ; No, Quit XOr AL,32 ;Adjust case of character @@CapsOff: Mov KeyASCII,AL ;Save the character ; Test KeyOpt,K_ENH+K_ALT+K_CTRL ;Has an extended key or key combination been pressed? ; JZ Short @@NoEvent ; Nope, Single letters can't trigger events Test AL,AL ;Has an extended key or letter been pressed? JZ Short @@NoEvent ; Nope, Nothing to trigger event Push ECX Mov BH,KeyOpt Mov BL,KeyOpt And BX,8770h ShR BL,4 Or BH,BL Mov AH,BH Mov BX,KeyList Mov CL,KeyENum Test CL,CL JZ Short @@NoKeys @@SearchKey: Cmp AX,[BX] JE Short @@CallEvent Add BX,6 Dec CL JNZ Short @@SearchKey @@NoKeys: Pop ECX @@NoEvent: Jmp Short @@GotKey @@CallEvent: Push EDX ESI EDI EBP Push ES FS GS Call Word Ptr [2+BX] Pop GS FS ES Pop EBP EDI ESI EDX ECX Jmp Short @@GotKey @@RShift: Or KeyOpt,K_SHIFTR Jmp Short @@GotKey @@LShift: Or KeyOpt,K_SHIFTL Jmp Short @@GotKey @@Ctrl: Test KeyFlag,K_EXT SetZ AL Dec AL And AL,K_CTRLL-K_CTRLR Add AL,K_CTRLR Or KeyOpt,AL Jmp Short @@GotKey @@Alt: Test KeyFlag,K_EXT SetZ AL Dec AL And AL,K_ALTL-K_ALTR Add AL,K_ALTR Or KeyOpt,AL Jmp Short @@GotKey @@GotKey: And KeyFlag,Not K_EXT Mov AL,20h ;Acknowledge interrupt Out 20h,AL Pop EBX EAX DS IRet KeyInt9 ENDP ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ ;Mouse Interrupt Handler ; ;Desc: ; This procedure is given to the mouse driver as an alternate handler. ; This routine will work in any 8x8 text mode so long as the page width is set to 128 characters, ; and sequential memory addressing is used instead of odd/even. ;In: ; BX = Buttons being pressed ; SI = X mickey counter ; DI = Y mickey counter ;Out: ; nothing ;Destroys: ; nothing ALIGN 16 RatInt33 PROC FAR ; PushA ;I'm not sure which, if any, registers the mouse ; Push DS ES ; driver preserves. Just to be safe... Mov AX,DATAMAIN ;Initialize data segment Mov DS,AX Test MStatus,M_NEW JZ Short @@CalcCur Mov BH,Byte Ptr AbsPosX Mov CX,AbsPosX ShR CX,3 Mov BL,0FFh Sub BL,Byte Ptr AbsPosY Mov DX,AbsPosY ShR DX,3 Mov CH,DL Mov Word Ptr RatX,-1 Jmp @@MouseOn @@CalcCur: And BL,7 Mov RatB,BL ;Set button flags ;Use mouse driver to determine cursor position IFDEF MSPos Mov EDI,DWord Ptr AbsPosX ;Get current absolute position Mov AbsPosX,CX Mov BH,CL ShR CX,3 Mov AbsPosY,DX Mov BL,0FFh Sub BL,DL ShR DX,3 Mov CH,DL Cmp EDI,DWord Ptr AbsPosX ;Has the cursor moved at all? ;Dertermine position internally ------------ ELSE Mov EDX,DWord Ptr AbsPosX ;Get current absolute position SAR SI,1 SAR DI,1 ;Calculate X pixels moved --------------- Mov AX,MickeyX ;AX = Previous mickey counter Mov MickeyX,SI ;Store new mickey counter Sub SI,AX ;SI = Number of pixels moved XOr AX,AX ;AX = Left edge of the screen Add SI,AbsPosX ;SI = New absolute position. Is it still on the screen? SetS AL ; No, AL = 1 Yes, AL = 0 Dec AX ;AX = 0 or FFFFh And AX,M_MAXX ;AX = Right edge of the screen if SI was not negative Cmp SI,M_MAXX ;Is cursor still on the screen? IFDEF Pent CMovB AX,SI ; Yes, AX = New position ELSE JAE Short @@XBound ; No, AX remains unchanged Mov AX,SI @@XBound: ENDIF Mov AbsPosX,AX ;Store new absolute position Mov BH,AL ShR AX,3 Mov CL,AL ;CL = New character position ;Calculate Y pixels moved --------------- Mov AX,MickeyY Mov MickeyY,DI Sub DI,AX XOr AX,AX Add DI,AbsPosY SetS AL Dec AX And AX,M_MAXY Cmp DI,M_MAXY IFDEF Pent CMovB AX,DI ELSE JAE Short @@YBound Mov AX,DI @@YBound: ENDIF Mov AbsPosY,AX Mov BL,0FFh Sub BL,AL ;Reverse BL ShR AX,3 Mov CH,AL Cmp EDX,DWord Ptr AbsPosX ;Has the cursor moved at all? ENDIF ;- MSPos JE @@NoMove ; No, Quit @@MouseOn: Mov AX,0B800h ;Point our way to video memory! Mov ES,AX Or MStatus,M_ABS ;Cursor has moved And BX,707h ;BH=X ofs in char BL=Y ofs in char (yes,it's backwards) ShL BL,1 ;Shift BL to compensate for word sized cursor mask Cmp Word Ptr RatX,CX ;Has the cursor moved to a new character? JE @@SameChar ; No, Don't waste time replacing underlying screen Mov Word Ptr RatX,CX ;Save new cursor position ShL CL,1 ;Account for attribute byte Add CX,WinPos ;Adjust cursor position for window location Test MStatus,M_VIS ;Is the cursor visible? JZ @@MouseOff ; No, Quit ;Replace old screen, erasing cursor Test MStatus,M_NEW JNZ Short @@NoUnder Mov DI,ChrPos Mov SI,Offset[ChrScr] Test MStatus,M_BLOCK JNZ Short @@RepBlk MovSD Add DI,256-4 MovSD Add DI,256-4 MovSW @@RepBlk: MovSW @@NoUnder: ;Replace screen with mouse cursor - Mov ChrPos,CX Mov DI,CX Test MStatus,M_Block JZ Short @@MakeCur Mov AX,ES:[DI] Mov ChrScr,AX Mov Byte Ptr ES:[DI+1],077h Jmp @@NoMove @@MakeCur: Mov SI,Offset[ChrScr] Mov DL,0D0h Mov CL,3 @@Place: Mov AX,ES:[DI] Mov [SI],AX Mov AL,DL Mov ES:[DI],AX Add SI,2 Add DI,2 Inc DL Mov AX,ES:[DI] Mov [SI],AX Mov AL,DL Mov ES:[DI],AX Inc DL Add SI,2 Add DI,256-2 Dec CL JNZ Short @@Place @@SameChar: Test MStatus,M_Block JNZ @@NoMove ClI Mov DX,V_Seq ;Switch to sequential mode Mov AX,704h Out DX,AX Mov AX,402h ;Write to bit plane 2 (character bitmaps) Out DX,AX ;Update characters with graphic cursor IFDEF MMX FSave MMXState Mov DI,0D0h*32 ;DI-> Character maps containing cursor MovZX ECX,BH ;MM4 = Amount to shift mask MovD MM4,CX Mov BH,0 ;BX = Location in mask Mov ESI,Offset[ChrScr] ;SI-> Underlying characters XOr EDX,EDX @@Mask: ;Load first character map---------- Mov DX,[ESI] ;DX = Character value/attribute Add ESI,2 ;Move to next character And DH,10h ;Isolate font bank bit ShR DH,1 ShL EDX,3 ;DX->Character bitmap Add EDX,DWord Ptr CharSet MovQ MM0,[EDX] ;Load character bitmap into MM0 and MM1 MovQ MM1,[EDX] ;Interleave second character map -- Mov DX,[ESI] Add ESI,2 And DH,10h ShR DH,1 ShL EDX,3 Add EDX,DWord Ptr CharSet PUnpckLBW MM0,[EDX] ;Interleave top half of character maps PUnpckHBW MM1,[EDX] ; " " lower half ;Load and adjust cursor mask ------ MovQ MM2,CurMask[EBX] ;Load mask into MMX MovQ MM3,CurMask[EBX+16] PSRAW MM2,MM4 ;Shift mask PSRAW MM3,MM4 PAnd MM0,MM2 ;Mask characters PAnd MM1,MM3 ;Load and adjust cursor black ----- MovQ MM2,CurBlack[EBX] ;Load black into MMX MovQ MM3,CurBlack[EBX+16] PSRLW MM2,MM4 ;Shift black PSRLW MM3,MM4 POr MM0,MM2 ;Write cursor onto characters POr MM1,MM3 ;Uninterleave new character maps -- MovQ MM2,MM0 ;Copy new character bitmaps MovQ MM3,MM1 PSRLW MM0,8 ;MM1:MM0 = First character (interleaved) PSRLW MM1,8 PackUSWB MM0,MM1 ;Pack first character into one bitmap MovQ ES:[EDI],MM0 ;Store first character into bitmap video memory MovQ ES:[EDI+16384],MM0 Add EDI,32 ;DI->Next character PAnd MM2,MMX_LBM ;Isolate second character (interleaved) PAnd MM3,MMX_LBM PackUSWB MM2,MM3 ;Pack second character into one bitmap MovQ ES:[EDI],MM2 ;Store second character into bitmap video memory MovQ ES:[EDI+16384],MM2 Add EDI,32 ;DI->Next character Cmp EDI,0D6h*32 ;Have all six characters been updated? JB @@Mask ; No FRStor MMXState ELSE Push BP Mov DI,0D0h*32 ;DI-> Characters containing cursor Mov CL,BH ;CL = Amount to shift mask Mov BH,0 ;BX = Location in mask Mov BP,Offset[ChrScr] ;BP-> Underlying characters Mov AH,3 ;AH = Three rows of characters to update @@Mask: MovZX SI,DS:[BP] ;Get first underlying character ShL SI,3 Add SI,Charset ;SI-> Character map Add BP,2 ;BP-> Next character Mov CH,8 ;CH = 8 rows of pixels @@CharCol1: Mov AL,[SI] ;Get byte of ASCII character map Mov DL,Byte Ptr CurMask[BX+1] ;DL = Cursor mask SAR DL,CL And AL,DL ;Clear bits used for mouse cursor Mov DH,Byte Ptr CurBlack[BX+1];DH = Cursor ShR DH,CL Or AL,DH ;Set bits used for mouse cursor Mov ES:[DI],AL ;Store character map Mov AL,[SI+2048] ;Get byte of graphic character map And AL,DL Or AL,DH Mov ES:[DI+16384],AL Add BX,2 Inc SI Inc DI Dec CH JNZ Short @@CharCol1 Sub BX,16 Add DI,24 MovZX SI,DS:[BP] ShL SI,3 Add SI,Charset Add BP,2 Mov CH,8 @@CharCol2: Mov DX,CurBlack[BX] ShR DX,CL Mov AL,DL Mov DX,CurMask[BX] SAR DX,CL Mov DH,AL Mov AL,[SI] And AL,DL Or AL,DH Mov ES:[DI],AL Mov AL,[SI+2048] And AL,DL Or AL,DH Mov ES:[DI+16384],AL Add BX,2 Inc SI Inc DI Dec CH JNZ Short @@CharCol2 Add DI,24 Dec AH JNZ @@Mask Pop BP ENDIF Mov DX,V_Seq ;Return to odd/even mode Mov AX,304h Out DX,AX Mov AL,02h ;Write to characters and attributes Out DX,AX StI @@NoMove: Test MStatus,M_VIS ;Is the cursor visible? JZ @@MouseOff ; No, Quit Test MStatus,M_NEW JNZ @@MouseOff Mov AL,RatB Cmp AL,RatBLast ;Has the button status changed? JE @@MouseOff ; No XOr AL,RatBLast ;AL = Buttons that were just pressed And AL,RatB Mov CH,RatB ;CH = Buttons that were just released XOr CH,RatBLast And CH,RatBLast ShL CH,4 ;CH = Event ID Or CH,AL Mov AL,RatB ;Save new status Mov RatBLast,AL Mov AX,Word Ptr RatX ;Get current location Add AX,WinPos Mov BX,RatList Mov CL,RatENum Test CL,CL JZ @@MouseOff @@ChkEvent: Test CH,[BX] ;Does button status trigger event? JZ Short @@NoEvent ; No Cmp AL,[BX+4] ;Is cursor located inside event window? JA Short @@NoEvent ; No Cmp AL,[BX+6] JB Short @@NoEvent Cmp AH,[BX+5] JA Short @@NoEvent Cmp AH,[BX+7] JB Short @@NoEvent Push BX CX DS FS GS ;Push needed registers Mov DX,0B800h ;Replace screen underlying cursor Mov ES,DX Mov DI,ChrPos Mov SI,Offset[ChrScr] Test MStatus,M_BLOCK JNZ Short @@Block MovSD Add DI,256-4 MovSD Add DI,256-4 MovSW @@Block: MovSW Or MStatus,M_EVENT Mov DX,[BX+8] ;Get function pointer Call DX ;Call function Pop GS FS DS Or MStatus,M_NEW Call RatInt33 And MStatus,Not (M_NEW+M_EVENT) Pop CX BX Mov AX,Word Ptr RatX ;Reload AX with location @@NoEvent: Add BX,12 Dec CL JNZ Short @@ChkEvent @@MouseOff: ; Pop ES DS ; PopA RetF RatInt33 ENDP ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ ;Capture Keyboard Interrupt ALIGN 16 CapKeybd PROC USES EAX,DX,BX,ES XOr EAX,EAX Mov DWord Ptr KeyASCII,EAX ;Reset keyboard variables Push DS ;Get current IRQ 1 vector --------------- Mov AX,3509h Int 21h Mov Word Ptr OldInt9,BX Mov Word Ptr OldInt9[2],ES Mov AX,2509h Mov DX,CS Mov DS,DX Mov DX,Offset[KeyInt9] Int 21h ; Mov DS,AX ; Mov EAX,DS:[9*4] ; Mov DS:[9*4+2],CS ; Mov Word Ptr DS:[9*4],Offset[KeyInt9] ;New vector ;Get BIOS switch states ----------------- Mov DX,40h Mov DS,DX Mov DL,DS:[17h] Pop DS ; Mov OldInt9,EAX ;Save old vector ;Store switch states -------------------- ShR DL,4 Mov KeyFlag,DL Ret CapKeybd ENDP ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ ;Release Keyboard Interrupt ALIGN 16 RelKeybd PROC USES EAX,DX,DS ;Load switch states --------------------- MovZX DX,KeyFlag ShL DL,4 Push DX XOr EAX,EAX Mov DWord Ptr KeyASCII,EAX ;Reset keyboard variables ;Restore IRQ 1 vector ------------------- Mov AX,2509h Mov DX,Word Ptr OldInt9 Mov DS,Word Ptr OldInt9[2] Int 21h ; Push OldInt9 ; Mov DS,AX ; Pop EAX ; Mov DS:[9*4],EAX ;Restore BIOS status bytes -------------- Pop DX Mov AX,40h Mov DS,AX Mov DS:[17h],DX ;Switch states ShR DL,4 And DL,7 Mov DS:[97h],DL ;LED states And Byte Ptr DS:[96h],30h ;Other stuff Ret RelKeybd ENDP ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ ;Check Keypress ALIGN 16 ChkKey PROC Test KeyFlag,K_CHAR Ret ChkKey ENDP ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ ;Get Keypress ALIGN 16 GetKey PROC @@WaitKey: Test KeyFlag,K_CHAR JZ Short @@WaitKey And KeyFlag,Not (K_CHAR+K_PRESS) Mov AH,KeyOpt Mov AL,KeyOpt And AX,8F70h ShR AL,4 Or AH,AL Mov AL,KeyASCII Ret GetKey ENDP ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ ;Check Keypress - Extended ALIGN 16 ChkKeyExt PROC Mov AL,KeyFlag And AL,8Fh Test KeyFlag,K_PRESS Ret ChkKeyExt ENDP ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ ;Get Keypress - Extended ALIGN 16 GetKeyExt PROC @@WaitKey: Test KeyFlag,K_PRESS JZ Short @@WaitKey And KeyFlag,Not (K_CHAR+K_PRESS) Mov AX,KeyPress Mov DX,KeyCode And DH,8Fh Ret GetKeyExt ENDP ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ ;Set Keypress Event List ALIGN 16 SetKeyList PROC ARG Num:Word,Lst:Word Mov AX,Num Mov KeyENum,AL Mov AX,Lst Mov KeyList,AX Ret SetKeyList ENDP ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ ;Setup Alternate Mouse Handler ALIGN 16 TrapRat PROC ARG CMap:Word,CType:Word ClI Mov AX,CMap Mov CharSet,AX Mov AX,CType Test AX,AX SetZ AL Dec AL And AL,M_BLOCK Or MStatus,AL Mov AX,21h ;Reset mouse driver Int 33h Cmp AX,21h ;Is AX unchanged? JE @@NoMouse ; Yes, No mouse driver is installed ; Mov AX,2 ;Hide mouse cursor, so the driver doesn't try to thwart ; Int 33h ; our plans ; Mov AX,1Fh ;Make mouse driver release video interrupt ; Int 33h ;(doesn't work under Windoze) ;Setup secondary mouse handler Mov AX,14h ;Xchg old handler with new one Mov CX,0011111b ;Interrupt on move, and rt/lf btn click/rel Mov DX,Offset[RatInt33] ;ES:[DX]->New handler Push ES Push CS Pop ES Int 33h Mov Word Ptr OldInt33,DX ;Save old handler, if there was one Mov Word Ptr OldInt33+2,ES Pop ES Or MStatus,M_NEW+M_VIS Mov AbsPosX,M_MAXX ShR 1 Mov AbsPosY,M_MAXY ShR 1 Mov RatB,0 Call RatInt33 And MStatus,Not M_NEW StI ClC Ret @@NoMouse: StC Ret TrapRat ENDP ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ ;Release Mouse Handler ALIGN 16 RelRat PROC Mov AX,14h ;Restore old handler Mov CX,0011111b LES DX,OldInt33 Int 33h ; Mov AX,20h ;Let mouse driver recapture video interrupt ; Int 33h Mov AX,21h ;Reset mouse driver anyway Int 33h Ret RelRat ENDP ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ ;Get Mouse Cursor Information ALIGN 16 ChkRat PROC Mov AX,Word Ptr RatX Mov BL,RatB Ret ChkRat ENDP ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ ;Set Mouse Click Event List ALIGN 16 SetRatList PROC ARG Num:Word,Lst:Word Mov AX,Num Mov RatENum,AL Mov AX,Lst Mov RatList,AX Ret SetRatList ENDP ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ ;Turn Off Mouse Cursor ALIGN 16 HideRat PROC USES ES,DI,SI Test MStatus,M_EVENT JNZ @@Exit Test MStatus,M_VIS JZ @@Hidden And MStatus,Not (M_VIS + M_ABS) ;Reset visible and moved flags Mov DI,0B800h Mov ES,DI ;ES-> Video memory Mov DI,ChrPos ;DI-> Current location on screen Mov SI,Offset[ChrScr] ;SI-> Underlying screen Test MStatus,M_BLOCK JNZ @@Block MovSD ;Restore a row of characters Add DI,256-4 ;Move to next row MovSD Add DI,256-4 MovSW @@Block: MovSW @@Hidden: Inc MHide @@Exit: Ret HideRat ENDP ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ ;Turn On Mouse Cursor ALIGN 16 ShowRat PROC USES BX,CX,DX,SI,DI Test MStatus,M_EVENT + M_VIS JNZ @@Exit Dec MHide JA Short @@NoShow Mov MHide,0 JC Short @@NoShow Or MStatus,M_NEW+M_VIS Call RatInt33 And MStatus,Not M_NEW @@NoShow: @@Exit: Ret ShowRat ENDP ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ ;Move Mouse Window ALIGN 16 MoveCage PROC ARG X:Word,Y:Word USES AX Call HideRat Mov AH,Byte Ptr Y Mov AL,Byte Ptr X ShL AL,1 Mov WinPos,AX Call ShowRat Ret MoveCage ENDP ;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ ;Move Mouse Cursor ALIGN 16 MoveRat PROC ARG X:Word,Y:Word USES AX Mov AX,M_MAXY Cmp Y,AX IFDEF Pent CMovB AX,Y ELSE JAE Short @@YBad Mov AX,Y @@YBad: ENDIF Mov AbsPosY,AX ShR AX,3 Mov RatY,AL Mov DH,AL Mov AX,M_MAXX Cmp X,AX IFDEF Pent CMovB AX,X ELSE JAE Short @@XBad Mov AX,X @@XBad: ENDIF Mov AbsPosX,AX ShR AX,3 Mov RatX,AL Mov DL,AL ;Move cursor ---------------------------- Test MStatus,M_VIS ;Is the cursor visible? JZ Short @@NoCur ; No, Quit Call HideRat ;Restore underlying screen Or MStatus,M_ABS ;Make ShowRat recreate character maps Call ShowRat ;Draw cursor at current location @@NoCur: Ret MoveRat ENDP CODEMAIN ENDS END