*****************************************************************************
*          SOLE MOUSE DRIVER   (position independent)                       *
* Compiler: PhxAss 4.36, Options: OPT=3                              ORHAN  *
*****************************************************************************
           MACHINE     MC68020
           INCLUDE     "exec/types.i"
           INCLUDE     "exec/memory.i"
           INCLUDE     "exec/execbase.i"
           INCLUDE     "exec/tasks.i"
           INCLUDE     "exec/macros.i"
           INCLUDE     "dos/dos.i"
           INCLUDE     "devices/input.i"
           INCLUDE     "devices/inputevent.i"
           INCLUDE     "devices/serial.i"
           INCLUDE     "hardware/cia.i"
           INCLUDE     "lvo/exec_lib.i"
           INCLUDE     "lvo/dos_lib.i"	

CIAB       EQU         $BFD000
LENBUF     EQU         4096
STKPAT     EQU         $01234567

           STRUCTURE   MyTaskBase,TC_SIZE
           APTR        my_NOTIFYTASK
           APTR        my_INPUTPORT
           APTR        my_INPUTREQ
           APTR        my_SERIALPORT
           APTR        my_SERIALREQ
           APTR        my_TIMERPORT
           APTR        my_TIMERREQ
           STRUCT      my_INPUTEVENT1,ie_SIZEOF       ;STRUCTURE InputEvent
           STRUCT      my_INPUTEVENT2,ie_SIZEOF       ;STRUCTURE InputEvent
           STRUCT      my_INPUTEVENT3,ie_SIZEOF       ;STRUCTURE InputEvent
           STRUCT      my_SERIALBUF,LENBUF
           UBYTE       my_MAINFLAG
           ALIGNLONG
           STRUCT      my_TaskStack,1024
           LABEL       my_StackEnd
           LABEL       MyTaskBase_Sizeof

           BITDEF      FLAG,OPENINPUT,0        ;0= closed, 1= opened
           BITDEF      FLAG,OPENSERIAL,1       ;0= closed, 1= opened
           BITDEF      FLAG,OPENTIMER,2        ;0= closed, 1= opened
           BITDEF      FLAG,LMB,3              ;left mouse button status
           BITDEF      FLAG,RMB,4              ;right mouse button status

           BITDEF      FLAGBYTE,FIRST,0        ;1= first byte exist
           BITDEF      FLAGBYTE,SECOND,8       ;1= second byte exist
*****************************************************************************
*          start                                                            *
*****************************************************************************
           SECTION     "CODE",CODE
           MOVE.L      ($4),A6
           CMP.W       #39,LIB_VERSION(A6)             ;check KS3.0
           BLT         AA0
           BTST.B      #AFB_68020,AttnFlags+1(A6)      ;check M68020
           BEQ         AA0

           LEA.L       INPUTNAME,A1
           CALLSYS     FindTask
           TST.L       D0
           BEQ         AA0
           MOVE.L      D0,A0
           MOVE.B      LN_PRI(A0),D7                   ;input.device task pri

           LEA.L       TCBMEMLIST,A0
           CALLSYS     AllocEntry
           BCLR.L      #31,D0
           BNE         AA0
           MOVE.L      D0,A2                           ;new memlist

           MOVE.L      TASKBASE-TCBMEMLIST(A2),A3      ;task base
           MOVE.L      TASKCODE-TCBMEMLIST(A2),A4      ;task code

           LEA.L       MYTASK,A0
           MOVE.L      A4,A1
           MOVE.L      #ENDCODE-MYTASK-1,D0
AA8:       MOVE.B      (A0)+,(A1)+
           DBF         D0,AA8

           CALLSYS     CacheClearU

           LEA.L       TC_MEMENTRY(A3),A0              
           MOVE.L      A2,A1                           
           NEWLIST     A0                              ;initialize list
           ADDHEAD                                     ;add new memlist

           MOVE.L      ThisTask(A6),my_NOTIFYTASK(A3)

           MOVE.B      #NT_TASK,LN_TYPE(A3)
           MOVE.B      D7,LN_PRI(A3)
           LEA.L       MYNAME-MYTASK(A4),A0
           MOVE.L      A0,LN_NAME(A3)
           LEA.L       my_TaskStack(A3),A0
           MOVE.L      #STKPAT,(A0)
           MOVE.L      A0,TC_SPLOWER(A3)
           LEA.L       my_StackEnd(A3),A0
           MOVE.L      A0,TC_SPUPPER(A3)
           MOVE.L      A0,TC_SPREG(A3)

           MOVE.L      A3,A1
           MOVE.L      A4,A2
           CLEARA      A3
           CALLSYS     AddTask

           MOVE.L      #SIGBREAKF_CTRL_E|SIGBREAKF_CTRL_F,D0
           CALLSYS     Wait
           BTST.L      #SIGBREAKB_CTRL_E,D0
           BEQ         AA0

           MOVE.L      #RETURN_OK,D3
           BRA         AA20
AA0:
           MOVE.L      #ERROR_NOT_IMPLEMENTED,D3

           LEA.L       DOSNAME,A1
           CLR.L       D0
           CALLSYS     OpenLibrary
           TST.L       D0
           BEQ         AA20

           MOVE.L      D0,A6
           MOVE.L      D3,D1
           CLR.L       D2
           CALLSYS     PrintFault

           MOVE.L      A6,A1
           MOVE.L      ($4),A6
           CALLSYS     CloseLibrary
AA20:
           MOVE.L      D3,D0
           RTS
*****************************************************************************
*          data                                                             *
*****************************************************************************
TCBMEMLIST:
           DCB.B       LN_SIZE                   ;STRUCTURE ML,LN_SIZE
           DC.W        2                         ;UWORD ML_NUMENTRIES
TASKBASE   DC.L        MEMF_PUBLIC|MEMF_CLEAR    ;LABEL ML_ME      (ME_REQS)
           DC.L        MyTaskBase_Sizeof         ;                 (ME_LENGTH)
TASKCODE   DC.L        MEMF_PUBLIC
           DC.L        ENDCODE-MYTASK

DOSNAME    DC.B        'dos.library',0
VERSION    DC.B        '$VER: SoleMouse 1.0 (01.9.97) © OR',13,10,0
           CNOP        0,4
*****************************************************************************
*****************************************************************************
**         my task                                                         **
*****************************************************************************
*****************************************************************************
MYTASK:
           MOVE.L      ($4),A6
           MOVE.L      ThisTask(A6),A5              ;data base

           CALLSYS     CreateMsgPort
           MOVE.L      D0,my_SERIALPORT(A5)
           BEQ         CLEANEXIT
           MOVE.L      D0,A0
           MOVE.L      #IOEXTSER_SIZE,D0
           CALLSYS     CreateIORequest
           MOVE.L      D0,my_SERIALREQ(A5)
           BEQ         CLEANEXIT

           CALLSYS     CreateMsgPort
           MOVE.L      D0,my_TIMERPORT(A5)
           BEQ         CLEANEXIT
           MOVE.L      D0,A0
           MOVE.L      #IOTV_SIZE,D0
           CALLSYS     CreateIORequest
           MOVE.L      D0,my_TIMERREQ(A5)
           BEQ         CLEANEXIT

           LEA.L       TIMENAME,A0
           MOVE.L      my_TIMERREQ(A5),A1
           MOVE.L      #UNIT_MICROHZ,D0
           CLR.L       D1
           CALLSYS     OpenDevice
           TST.L       D0
           BNE         CLEANEXIT
           BSET.B      #FLAGB_OPENTIMER,my_MAINFLAG(A5)

           CALLSYS     CreateMsgPort
           MOVE.L      D0,my_INPUTPORT(A5)
           BEQ         CLEANEXIT
           MOVE.L      D0,A0
           MOVE.L      #IOSTD_SIZE,D0
           CALLSYS     CreateIORequest
           MOVE.L      D0,my_INPUTREQ(A5)
           BEQ         CLEANEXIT

           LEA.L       INPUTNAME,A0
           MOVE.L      my_INPUTREQ(A5),A1
           CLR.L       D0
           CLR.L       D1
           CALLSYS     OpenDevice
           TST.L       D0
           BNE         CLEANEXIT
           BSET.B      #FLAGB_OPENINPUT,my_MAINFLAG(A5)

           MOVE.L      my_SERIALREQ(A5),A0
           LEA.L       MN_SIZE(A0),A0
           MOVE.L      #IOEXTSER_SIZE-MN_SIZE-1,D0
AA9:       CLR.B       (A0)+
           DBF         D0,AA9

           LEA.L       SERNAME,A0
           MOVE.L      my_SERIALREQ(A5),A1
           MOVE.B      #SERF_RAD_BOOGIE|SERF_XDISABLED,D7
           MOVE.B      D7,IO_SERFLAGS(A1)
           CLR.L       D0
           CLR.L       D1
           CALLSYS     OpenDevice
           TST.L       D0
           BNE         CLEANEXIT
           BSET.B      #FLAGB_OPENSERIAL,my_MAINFLAG(A5)

           MOVE.L      #1200,D2
AA46:
           MOVE.L      my_SERIALREQ(A5),A1
           MOVE.W      #SDCMD_SETPARAMS,IO_COMMAND(A1)
           MOVE.B      D7,IO_SERFLAGS(A1)
           MOVE.B      #7,IO_READLEN(A1)
           MOVE.B      #1,IO_STOPBITS(A1)
           MOVE.L      D2,IO_BAUD(A1)           ;no button= 1200, LMB= 2400, RMB= 4800
           MOVE.L      #LENBUF,IO_RBUFLEN(A1)
           LEA.L       my_SERIALBUF(A5),A0
           MOVE.L      A0,IO_DATA(A1)
           CALLSYS     DoIO
           TST.L       D0
           BNE         CLEANEXIT

           BSR         DELAY

           MOVE.L      my_SERIALREQ(A5),A1
           MOVE.W      #CMD_CLEAR,IO_COMMAND(A1)
           CALLSYS     DoIO

           CALLSYS     Disable
           OR.B        #CIAF_COMDTR|CIAF_COMRTS,(CIAB+ciapra)   ;mouse should send 'M'
           NOP
           NOP
           NOP
           NOP
           AND.B       #~(CIAF_COMDTR|CIAF_COMRTS),(CIAB+ciapra)
           CALLSYS     Enable

           BSR         DELAY
AA41:
           MOVE.L      my_SERIALREQ(A5),A1
           MOVE.W      #SDCMD_QUERY,IO_COMMAND(A1)
           CALLSYS     DoIO
           MOVE.L      my_SERIALREQ(A5),A1
           TST.L       IO_ACTUAL(A1)
           BEQ         AA42
           MOVE.W      #CMD_READ,IO_COMMAND(A1)
           MOVE.L      #1,IO_LENGTH(A1)
           CALLSYS     DoIO
           TST.L       D0
           BNE         AA42

           MOVE.B      my_SERIALBUF(A5),D0
           AND.B       #$7F,D0
           CMP.B       #'M',D0
           BEQ         AA43
           BRA         AA41
AA42:
           LSL.L       #1,D2
           CMP.L       #4800,D2
           BLS         AA46
           BRA         CLEANEXIT
AA43:
           MOVE.L      my_NOTIFYTASK(A5),A1
           MOVE.L      #SIGBREAKF_CTRL_E,D0
           CALLSYS     Signal
           BRA         AA36
*****************************************************************************
*          delay                                                            *
*****************************************************************************
DELAY:
           MOVE.L      my_TIMERREQ(A5),A1
           MOVE.W      #TR_ADDREQUEST,IO_COMMAND(A1)
           LEA.L       IOTV_TIME(A1),A0
           CLR.L       TV_SECS(A0)
           MOVE.L      #100000,TV_MICRO(A0)
           CALLSYS     DoIO
           RTS
*****************************************************************************
*          clean exit                                                       *
*****************************************************************************
CLEANEXIT:
           BTST.B      #FLAGB_OPENTIMER,my_MAINFLAG(A5)
           BEQ         AA44
           MOVE.L      my_TIMERREQ(A5),A1
           CALLSYS     CloseDevice
AA44:
           MOVE.L      my_TIMERREQ(A5),A0
           TST.L       A0
           BEQ         AA45
           CALLSYS     DeleteIORequest
AA45:
           MOVE.L      my_TIMERPORT(A5),A0
           TST.L       A0
           BEQ         AA48
           CALLSYS     DeleteMsgPort
AA48:
           BTST.B      #FLAGB_OPENSERIAL,my_MAINFLAG(A5)
           BEQ         AA1
           MOVE.L      my_SERIALREQ(A5),A1
           CALLSYS     CloseDevice
AA1:
           MOVE.L      my_SERIALREQ(A5),A0
           TST.L       A0
           BEQ         AA2
           CALLSYS     DeleteIORequest
AA2:
           MOVE.L      my_SERIALPORT(A5),A0
           TST.L       A0
           BEQ         AA3
           CALLSYS     DeleteMsgPort
AA3:
           BTST.B      #FLAGB_OPENINPUT,my_MAINFLAG(A5)
           BEQ         AA4
           MOVE.L      my_INPUTREQ(A5),A1
           CALLSYS     CloseDevice
AA4:
           MOVE.L      my_INPUTREQ(A5),A0
           TST.L       A0
           BEQ         AA5
           CALLSYS     DeleteIORequest
AA5:
           MOVE.L      my_INPUTPORT(A5),A0
           TST.L       A0
           BEQ         AA6
           CALLSYS     DeleteMsgPort
AA6:
           MOVE.L      my_NOTIFYTASK(A5),A1
           MOVE.L      #SIGBREAKF_CTRL_F,D0
           CALLSYS     Signal

           MOVE.L      #0,D0
           RTS
*****************************************************************************
*          main loop                                                        *
*****************************************************************************
AA36:
           MOVE.L      my_SERIALREQ(A5),A4
           CLR.L       D5                    ;flag
           CLR.L       D3                    ;delta x
           CLR.L       D4                    ;delta y
AA34:
           CLR.L       D5

           MOVE.L      A4,A1
           MOVE.W      #CMD_CLEAR,IO_COMMAND(A1)
           CALLSYS     DoIO
AA33:
           MOVE.L      A4,A1
           MOVE.W      #SDCMD_QUERY,IO_COMMAND(A1)
           CALLSYS     DoIO
           MOVE.L      IO_ACTUAL(A4),D6
           BNE         AA32
           MOVE.L      #1,D6
AA32:
           MOVE.L      A4,A1
           MOVE.W      #CMD_READ,IO_COMMAND(A1)
           MOVE.L      D6,IO_LENGTH(A1)
           CALLSYS     DoIO
           TST.L       D0
           BNE         AA34

           LEA.L       my_SERIALBUF(A5),A3
AA7:
           SUB.L       #1,D6
           BMI         AA33
           MOVE.B      (A3)+,D0
           BTST.L      #6,D0
           BEQ         AA11
           MOVE.B      D0,D7
           CMP.L       #2,D6
           BLO         AA31
           SUB.L       #2,D6
           MOVE.W      (A3)+,D0
           BFEXTU      D0{18:06},D2
           BRA         AA12
AA31:      MOVE.L      #FLAGBYTEF_FIRST,D5
           BRA         AA7
AA11:      TST.B       D5
           BEQ         AA7
           BSET.L      #FLAGBYTEB_SECOND,D5
           BNE         AA12
           MOVE.B      D0,D2
           BRA         AA7
AA12:      CLR.L       D5

;-----------------------;
; 7  6  5  4  3  2  1  0;
; -  1  L  R Y7 Y6 X7 X6;
;-----------------------;
; 7  6  5  4  3  2  1  0;
; -  0 X5 X4 X3 X2 X1 X0;
;-----------------------;
; 7  6  5  4  3  2  1  0;
; -  0 Y5 Y4 Y3 Y2 Y1 Y0;
;-----------------------;

           BFINS       D7,D2{24:02}
           LSR.L       #2,D7
           BFINS       D7,D0{24:02}
           EXT.W       D2
           EXT.W       D0

           ADD.W       D2,D3
           ADD.W       D0,D4

           TST.L       D6
           BGT         AA7

           LEA.L       my_INPUTEVENT1(A5),A0
           CLR.L       ie_NextEvent(A0)
           MOVE.B      #IECLASS_RAWMOUSE,ie_Class(A0)
           CLR.B       ie_SubClass(A0)
           CLR.L       ie_EventAddress(A0)

           BTST.B      #3,D7
           BNE         AA13
           BCLR.B      #FLAGB_LMB,my_MAINFLAG(A5)
           BEQ         AA15
           MOVE.W      #IECODE_UP_PREFIX|IECODE_LBUTTON,ie_Code(A0)
           CLR.W       ie_Qualifier(A0)
           BRA         AA14
AA13:      BSET.B      #FLAGB_LMB,my_MAINFLAG(A5)
           BNE         AA15
           MOVE.W      #IECODE_LBUTTON,ie_Code(A0)
           MOVE.W      #IEQUALIFIER_LEFTBUTTON,ie_Qualifier(A0)
AA14:      BSR         WRITEEVENT
AA15:
           LEA.L       my_INPUTEVENT2(A5),A0
           CLR.L       ie_NextEvent(A0)
           MOVE.B      #IECLASS_RAWMOUSE,ie_Class(A0)
           CLR.B       ie_SubClass(A0)
           CLR.L       ie_EventAddress(A0)

           BTST.B      #2,D7
           BNE         AA17
           BCLR.B      #FLAGB_RMB,my_MAINFLAG(A5)
           BEQ         AA16
           MOVE.W      #IECODE_UP_PREFIX|IECODE_RBUTTON,ie_Code(A0)
           CLR.W       ie_Qualifier(A0)
           BRA         AA18
AA17:      BSET.B      #FLAGB_RMB,my_MAINFLAG(A5)
           BNE         AA16
           MOVE.W      #IECODE_RBUTTON,ie_Code(A0)
           MOVE.W      #IEQUALIFIER_RBUTTON,ie_Qualifier(A0)
AA18:      BSR         WRITEEVENT
AA16:
           SWAP.W      D3
           OR.L        D4,D3
           BEQ         AA33

           LEA.L       my_INPUTEVENT3(A5),A0
           CLR.L       ie_NextEvent(A0)
           MOVE.B      #IECLASS_RAWMOUSE,ie_Class(A0)
           CLR.B       ie_SubClass(A0)
           MOVE.W      #IECODE_NOBUTTON,ie_Code(A0)
           MOVE.W      #IEQUALIFIER_RELATIVEMOUSE,ie_Qualifier(A0)
           MOVE.L      D3,ie_EventAddress(A0)
           BSR         WRITEEVENT

           CLR.L       D3
           CLR.L       D4

           CMP.L       #STKPAT,my_TaskStack(A5)    ;check stack overflow
           TRAPNE
           BRA         AA33
*****************************************************************************
*          write event   A0= InputEvent                                     *
*****************************************************************************
WRITEEVENT:
           MOVE.L      my_INPUTREQ(A5),A1
           MOVE.W      #IND_WRITEEVENT,IO_COMMAND(A1)
           MOVE.L      A0,IO_DATA(A1)
           MOVE.L      #ie_SIZEOF,IO_LENGTH(A1)
           CALLSYS     DoIO
           RTS
*****************************************************************************
*          data                                                             *
*****************************************************************************
MYNAME     DC.B        'SoleMouse',0
INPUTNAME  DC.B        'input.device',0
SERNAME    DC.B        'serial.device',0
TIMENAME   DC.B        'timer.device',0
ENDCODE:
           END
