'===========================================================================
' Subject: PB MOUSE TIC-TAC-TOE DEMO          Date: 04-08-96 (12:00)       
'  Author: The ABC Programmer                 Code: PB                     
'  Origin: Advanced Assembly Language       Packet: MOUSE.ABC
'===========================================================================
'===================================================
' PB Mouse Demo Programmed by William Yu (04-08-96)
' All? Interrupt 33h Mouse Routines implemented.
' Please use and distribute freely.
' Interrupt 33h routines courtesy of the ADVANCED
' ASSEMBLY LANGUAGE book by Peter Norton.
'
' NOTE: Mouse routines are NOT harmful even if the
'       user does not have a mouse driver installed.
'       So you don't need mouse checking routines
'       scattered all over your code.
'       ie.  MouseInstalled = MouseExist%
'            If MouseInstalled Then
'               MouseShow
'               blah blah blah
'            End If
'
' DRAG 'N DROP
'   Use MouseInfo (Drag = Button > 0)
'                 (Drop = Button = 0)
'   Or use MouseQueue and MouseRelease
' HOLD BUTTON ACTIVATED
'   MouseInfo continually reads mouse button info
' HOLD BUTTON DE-ACTIVATED
'   MouseQueue - how many times was the mouse
'        button pressed since last poll?
'
' Although everything can revolve around the one
' routine MouseInfo, there are times when you
' cannot poll the mouse information every second.
' Use MouseQueue as a substitute.
'===================================================
DEFINT A-Z: CLS

%FLAGS = 0
%AX = 1
%BX = 2
%CX = 3
%DX = 4
%SI = 5
%DI = 6
%BP = 7
%DS = 8
%ES = 9

%False = 0
%True = NOT %False

%LeftButton         = 1
%RightButton        = 2
%LeftRightButtons   = 3
%CenterButton       = 4
%LeftCenterButtons  = 5
%RightCenterButtons = 6
%AllThreeButtons    = 7

SHARED Char, Char2           ' Or you can add extra params to CheckBox ()

IF NOT MouseExist% THEN Print "Mouse required for this demo.": END

PlayTICTACTOE             ' ESC or Right mouse button to quit demo.

FUNCTION MouseExist%      ' Call this first to initialize the mouse
   Reg %AX, 0
   CALL Interrupt &h33
   MouseExist%=Reg(%AX)   ' NON-Zero value means mouse driver loaded
   '----------------------' An alternative route with inline assembly
   '! Mov Ax, 0           '
   '! Int &h33            ' Interrupt 33h Service 0
   '! Cmp Ax, 0           ' Compare Carry Flag Set AX
   '! Jne Init            ' If not equal to 0 then mouse driver exists
   'MouseExist% = %False  ' Else driver not found
   'EXIT FUNCTION         '
   'Init:                 '
   'MouseExist% = %True   '
   '----------------------'
END FUNCTION

SUB MouseShow            ' Displays Mouse Cursor
   ! Mov Ax, 1           ' Interrupt 33h Service 1
   ! Int &h33
END SUB

SUB MouseHide            ' Hide Mouse Cursor
   ! Mov Ax, 2           ' Interrupt 33h Service 2
   ! Int &h33
END SUB

SUB MouseInfo (Button%, Column%, Row%)   ' Gets Mouse Position and Button Status
   Reg %AX, 3
   CALL Interrupt &h33
   Button% = Reg(%BX)         ' 1 = Left, 2 = Right, 3 = Both, 4 = Center
   Column% = Reg(%CX)/8 + 1   ' Remember that it returns in pixels
   Row% = Reg(%DX)/8 + 1
END SUB

SUB MouseCursor (MColumn%, MRow%)
   Reg %AX, 4
   Reg %CX, MColumn% * 8 - 1
   Reg %DX, MRow% * 8 - 1
   CALL Interrupt &h33
END SUB

SUB MouseQueue (ButtonInfo%, ButtonPress%, ButtonCol%, ButtonRow%)
   Reg %AX, 5                ' Returns ButtonPress%/Col%/Row% values
   Reg %BX, ButtonInfo%      ' 0 = Left Button, 1 = Right Button, 3 = Center?
   CALL Interrupt &h33
   ButtonPress% = Reg(%BX)   ' # Times button was pressed since last inquiry
   ButtonCol% = Reg(%CX)/8+1 ' Current mouse cursor column
   ButtonRow% = Reg(%DX)/8+1 ' Current mouse cursor row
END SUB

SUB MouseRelease (ButtonInfo%, ButtonPress%, ButtonCol%, ButtonRow%)
   Reg %AX, 6                ' Returns ButtonPress%/Col%/Row% values
   Reg %BX, ButtonInfo%      ' 0 = Left Button, 1 = Right Button, 3 = Center?
   CALL Interrupt &h33
   ButtonPress% = Reg(%BX)   ' # Times button was released since last inquiry
   ButtonCol% = Reg(%CX)     ' Current mouse cursor column
   ButtonRow% = Reg(%DX)     ' Current mouse cursor row
END SUB

SUB MouseLimits (LeftCol%, RightCol%, TopRow%, BottomRow%)
   Reg %AX, 7                   ' Horizontal Limits
   Reg %CX, RightCol% * 8 - 1
   Reg %DX, LeftCol% * 8 - 1
   CALL Interrupt &h33
   Reg %AX, 8                   ' Vertical Limits
   Reg %CX, TopRow% * 8 - 1
   Reg %DX, BottomRow% * 8 - 1
   CALL Interrupt &h33
END SUB

SUB MouseShape (ScrMaskChar%, ScrMaskAttr%, CurMaskChar$, CurMaskAttr%)
   Reg %BX, 0       ' 0 = Set Software Cursor  1 = Set Hardware Cursor
   Reg %CX, (ScrMaskAttr% * 256) + ScrMaskChar%
   Reg %DX, (CurMaskAttr% * 256) + ASC(CurMaskChar$)
   Reg %AX, 10
   CALL Interrupt &h33
END SUB

SUB CheckBox (Occupied(), Y%, X%, YCor%, XCor%)
   If NOT Occupied(Y%,X%) Then     ' Box is empty
     Locate YCor%, XCor%: Color 15: Print Chr$(Char)
     Occupied(Y%,X%) = %True       ' Make Box occupied
   Else                            ' Box is occupied
     Swap Char, Char2              ' Return to normal cursor state
   End If
END SUB

SUB PlayTICTACTOE               ' Not exactly, but it's just a DEMO
   DIM Occupied(3,3)            ' Make sure we don't overlap moves
   DIM Grid$(0 to 6)
   
   Grid$(0) = "+---+---+---+"   ' TIC-TAC-TOE Grid
   Grid$(1) = "|   |   |   |"   ' Only for demonstration purposes
   Grid$(2) = "+---+---+---+"   ' Not a functional game
   Grid$(3) = "|   |   |   |"   ' That would require some additional work
   Grid$(4) = "+---+---+---+"
   Grid$(5) = "|   |   |   |"
   Grid$(6) = "+---+---+---+"
   Char  = ASC("X")             ' Put into variables for easy swapping
   Char2 = ASC("O")             ' Change characters if desired
   
   MouseShape 0,0,Chr$(Char),14 ' X goes first
   XCor% = 10                   ' You can modify these values to move the
   YCor% = 6                    ' playing grid around.
   MouseLimits XCor%,XCor%+12,YCor%,YCor%+6   ' Restricts the mouse to playing grid
   MouseCursor XCor%, YCor%
   
   For Y = 0 to 6               ' Draw Playing Grid
     Locate Y+YCor%, XCor%: Print Grid$(Y)
   Next Y
   
   MouseShow
   
   DO
      MouseInfo MouseButton%, MouseCol%, MouseRow% ' Updates mouse information
      MouseQueue 0, Button%, Column%, Row%         ' Does not allow for button hold
      Locate 1,1: Color 7: Print MouseButton%,MouseCol%,MouseRow%
      
    If Button% Then
      InGrid% = %False
      SELECT CASE Row%
         Case YCor% + 1
           InGrid% = %True
           Grid = 1
         Case YCor% + 3
           InGrid = %True
           Grid = 2         
         Case YCor% + 5
           InGrid = %True
           Grid = 3         
         Case Else
           Swap Char, Char2
      END SELECT
   
   If InGrid Then
     SELECT CASE Column%
         Case XCor%+1 to XCor%+3
           CheckBox Occupied(), Grid, 1, Row%, XCor%+2
         Case XCor%+5 to XCor%+7
           CheckBox Occupied(), Grid, 2, Row%, XCor%+6
         Case XCor%+9 to XCor%+11
           CheckBox Occupied(), Grid, 3, Row%, XCor%+10
         Case Else
           Swap Char, Char2
     END SELECT
   End If
   
    Swap Char, Char2               ' X -> O and vice versa
    MouseShape 0,0,Chr$(Char),14   ' Update mouse cursor
    End if
   
  LOOP Until Inkey$<>"" OR MouseButton% = %RightButton

  MouseLimits 1,80,1,25      ' Restore normal limits
  MouseShape 0,0,Chr$(8),7   ' Restore normal mouse cursor???
END SUB
