home *** CD-ROM | disk | FTP | other *** search
/ Frozen Fish 1: Amiga / FrozenFish-Apr94.iso / bbs / alib / d9xx / d979 / qmouse.lha / QMouse / qmouse.s < prev   
Text File  |  1994-04-04  |  41KB  |  2,052 lines

  1. ;QMouse.s
  2. ;Written by Dan Babcock
  3.  
  4. ;This source was assembled with Macro68 release 3.
  5.  
  6.     exeobj
  7.     objfile    'c:QMouse'
  8.     MC68000
  9.     multipass
  10.  
  11. ;Set INFO_LEVEL to 1 for full debugging output.
  12. INFO_LEVEL    equ    0
  13.  
  14. ;Put a message to the serial port.  Used like so:
  15. ;
  16. ;PUTDEBUG    <'Init: called'>
  17. ;
  18. ;Parameters can be printed out by pushing them on the stack and
  19. ;adding the appropriate C printf-style % formatting commands.
  20.  
  21. PUTDEBUG     macro    ;<msg>
  22.     ifne    INFO_LEVEL
  23.     movem.l    d0-d1/a0-a1,-(sp)
  24.     lea    .msg\@(pc),a0    ;Point to static format string
  25.     lea    16(sp),a1    ;Point to args
  26.     bsr    KPutFmt
  27.     movem.l    (sp)+,d0-d1/a0-a1
  28.     bra    .end\@
  29. .msg\@:
  30.     dc.b    \1,$a,0
  31.     even
  32. .end\@:
  33.     endc
  34.     endm
  35.  
  36.  
  37. MAXQUEUE    equ    32
  38. SCREENLISTSIZE    equ    32    ;maximum number of screens to keep track of
  39. POINTERLISTSIZE    equ    32
  40. HANDLERPRI    equ    60    ;priority of input.device handler
  41. TaskPriority    equ    21
  42. ShellPriority    equ    0
  43. MaxCopperSize    equ    500
  44.  
  45. SysBackground    equ    $e    ;offset into gb_copinit copper list
  46. WindowStart    equ    $0    ;offset into LOF copper list
  47. DefColor    equ    $fff    ;white
  48. WaitLine    equ    $16
  49.  
  50.     move.l    4,a6
  51. ;Allocate global data structure
  52.     move.l    #Data_Sizeof,d0
  53.     move.l    #MEMF_CLEAR,d1
  54.     SYS    AllocMem
  55.     tst.l    d0
  56.     beq    .ErrEnd
  57.         move.l    d0,a5
  58.     lea    GlobalPtr(pc),a0
  59.     move.l    a5,(a0)
  60.  
  61. ;Allocate chip RAM data.
  62.     move.l    #CData_Sizeof,d0
  63.     move.l    #MEMF_CLEAR+MEMF_CHIP,d1
  64.     SYS    AllocMem
  65.     move.l    d0,ChipData(a5)
  66.     beq    CleanUp
  67.  
  68. ;Initialize static data
  69.     move.b    #HANDLERPRI,InputInterrupt+LN_PRI(a5)
  70.     move.l    a5,InputInterrupt+IS_DATA(a5)
  71.     moveq    #1,d0
  72.     move.l    d0,ClickCount(a5)
  73.  
  74. ;Open libraries
  75.     lea    LibTable(pc),a2
  76.     move.l    a2,a3
  77.     moveq    #NumLibs-1,d2
  78. .OLibLoop:
  79.     move.w    (a2)+,a1
  80.     add.l    a3,a1
  81.     SYS    OldOpenLibrary
  82.     move.w    (a2)+,a0
  83.     add.l    a5,a0
  84.     move.l    d0,(a0)
  85.     beq    CleanUp
  86.     dbra    d2,.OLibLoop
  87.  
  88. ;Parse command line
  89.     lea    Template(pc),a0
  90.     move.l    a0,d1
  91.     lea    Options(a5),a0
  92.     move.l    a0,d2
  93.     moveq    #0,d3    ;no custom rdarg structure
  94.     move.l    DosBase(a5),a6
  95.     SYS    ReadArgs
  96.     move.l    d0,ArgPtr(a5)
  97.     bne    .ArgsOK
  98.     lea    BadArgs(pc),a0
  99.     move.l    a0,d1
  100.     SYS    VPrintf
  101.     bra    CleanUp
  102.  
  103. .ErrEnd:    moveq    #RETURN_FAIL,d0
  104.     rts
  105.  
  106. .ArgsOK:
  107.     move.l    4,a6
  108.  
  109. ;Process QUIT option, if selected.
  110.     tst.l    QuitOption(a5)
  111.     beq    .SkipQuit
  112.     lea    ProcName(pc),a1
  113.     SYS    FindTask
  114.     tst.l    d0
  115.     beq    CleanUp
  116.     move.l    d0,a1
  117.     move.l    TC_Userdata(a1),a0
  118.     move.l    QuitSig(a0),d0
  119.     SYS    Signal    ;tell task to quit
  120.     bsr    CleanUp
  121.     bra    .Exit
  122. .SkipQuit:
  123.  
  124. ;If already installed, kill the existing process.
  125.     lea    ProcName(pc),a1
  126.     SYS    FindTask
  127.     tst.l    d0
  128.     beq    .NotInstalled
  129.     move.l    d0,a1
  130.     move.l    TC_Userdata(a1),a0
  131.     move.l    QuitSig(a0),d0
  132.     SYS    Signal    ;tell task to quit
  133.  
  134.     moveq    #26,d2
  135. .Kill:    subq.l    #1,d2
  136.     beq    .Exit
  137.     move.l    DosBase(a5),a6
  138.     moveq    #2,d1
  139.     SYS    Delay
  140.     lea    ProcName(pc),a1
  141.     move.l    4,a6
  142.     SYS    FindTask
  143.     tst.l    d0
  144.     bne    .Kill
  145. .NotInstalled:
  146.  
  147. ;Get stack for command.
  148.     move.l    DosBase(a5),a6
  149.     SYS    Cli
  150.     move.l    d0,a0
  151.     move.l    cli_DefaultStack(a0),d0
  152.     lsl.l    #2,d0
  153.     lea    CmdStackSize(pc),a0
  154.     move.l    d0,(a0)
  155.     move.l    4,a6
  156.  
  157. ;Perform relocations.
  158.     lea    RelocTable(pc),a0
  159.     lea    ResidentCode(a5),a1    ;destination
  160.     lea    StartAllocCode(pc),a2
  161.     moveq    #NumRelocs-1,d0
  162. .RLoop:    move.w    (a0)+,d2
  163.     move.l    (a2,d2.w),d1
  164.     add.l    a1,d1
  165.     move.l    d1,(a2,d2.w)
  166.     dbra    d0,.RLoop
  167.  
  168. ;Copy resident part of code into allocated memory
  169.     lea    StartAllocCode(pc),a0    ;source
  170. ;    lea    ResidentCode(a5),a1    ;destination
  171.     move.l    #ResidentCodeSize,d0    ;size
  172.     SYS    CopyMem
  173.     SYS    CacheClearU    ;for 020/030/040
  174.  
  175. ;Start a process
  176.     move.l    DosBase(a5),a6
  177.     lea    ResidentCode(a5),a0
  178.     lea    EntryPoint(pc),a1
  179.     move.l    a0,(a1)
  180.     lea    ProcName-StartAllocCode+ResidentCode(a5),a0
  181.     lea    ProcNamePtr(pc),a1
  182.     move.l    a0,(a1)
  183.     lea    NewProcTags(pc),a0
  184.     move.l    a0,d1
  185.     SYS    CreateNewProc
  186.  
  187. ;Exit back to CLI
  188. .Exit:    moveq    #0,d0
  189.     rts
  190.  
  191. RelocTable:
  192.     dc.w    reloc1-StartAllocCode
  193.     dc.w    reloc2-StartAllocCode
  194.     dc.w    reloc3-StartAllocCode
  195.     dc.w    reloc4-StartAllocCode
  196. EndRelocTable:
  197. NumRelocs    equ    (EndRelocTable-RelocTable)/2
  198.  
  199. ***************************************************************************
  200. * The following code is copied into allocated memory.                     *
  201. ***************************************************************************
  202.  
  203. StartAllocCode:
  204.     move.l    4,a6
  205.     move.l    GlobalPtr(pc),a5
  206.     lea    IntRoutine(pc),a0
  207.     move.l    a0,InputInterrupt+IS_CODE(a5)
  208.  
  209. ;Initialize damping constant.
  210.     move.l    AccelOption(a5),d0
  211.     beq    .NoDamp
  212.     move.l    d0,a0
  213.     move.l    (a0),d0
  214.     subq.l    #1,d0
  215.     move.l    ThreshOption(a5),d1
  216.     beq    .DefThresh
  217.     move.l    d1,a0
  218.     move.l    (a0),d1
  219. .DefThresh:
  220.     addq.l    #1,d1
  221.     muls.w    d0,d1
  222.     move.w    d1,DampingConstant(a5)
  223. .NoDamp:
  224.  
  225. ;Allocate signals
  226.     moveq    #NumSigs-1,d2
  227.     lea    Sigs(a5),a2
  228. .SigLoop:    moveq    #-1,d0
  229.     SYS    AllocSignal
  230.     tst.l    d0
  231.     bmi    CleanUp
  232.     moveq    #0,d1
  233.     bset    d0,d1
  234.     move.l    d1,(a2)+
  235.     dbra    d2,.SigLoop
  236.  
  237. ;Initialize semaphore(s)
  238.     lea    Semaphores(a5),a2
  239.     moveq    #NumSemaphores-1,d2
  240. .InitSema:
  241.     move.l    a2,a0
  242.     SYS    InitSemaphore
  243.     lea    SS_SIZE(a2),a2
  244.     dbra    d2,.InitSema
  245.  
  246.     move.l    ThisTask(a6),a0
  247.     move.l    a0,Task(a5)
  248.     move.l    a5,TC_Userdata(a0)
  249.  
  250. ;Install no-flicker option if selected.
  251.     tst.l    FlickerOption(a5)
  252.     beq    .NoFlicker
  253.     move.l    GraphBase(a5),a0
  254.     move.l    gb_copinit(a0),a0
  255.     move.l    a0,OriginalCopInit(a5)
  256.     move.l    ChipData(a5),a1
  257.     lea    Copper(a1),a1
  258.     move.l    a1,a2
  259.     move.w    #MaxCopperSize/4-1,d0
  260. .CLoop:    move.l    (a0)+,d1
  261.     cmp.l    #$008A0000,d1
  262.     beq    .CopEnd
  263.     move.l    d1,(a1)+
  264.     dbra    d0,.CLoop
  265.     clr.l    FlickerOption(a5)
  266.     bra    .NoFlicker
  267. .CopEnd:    move.l    #$01800000,(a1)+
  268.     move.l    a1,WaitLineAddress(a5)
  269.     move.l    #$1607FFFE,(a1)+
  270.     move.w    #$0180,(a1)+
  271.     move.l    #$008A0000,2(a1)
  272.     move.l    a1,RealBackground(a5)
  273.     move.l    a2,cop1lc+_custom
  274.     move.l    GraphBase(a5),a0
  275.     move.l    a2,gb_copinit(a0)
  276.     cmp.w    #color,SysBackground-2(a2)
  277.     bne    .DefColor
  278.     move.w    SysBackground(a2),(a1)
  279.     bra    .NoFlicker
  280. .DefColor:
  281.     move.w    #DefColor,(a1)
  282. .NoFlicker:
  283.  
  284. ;Patch MANY system routines.
  285.     SYS    Forbid
  286.     lea    PatchTable(pc),a2
  287.     move.l    a2,a3
  288. .Patch:    move.w    (a2)+,d0    ;get base
  289.     beq    .EndPatch
  290.     move.l    (a5,d0.w),a1    ;library base to patch
  291.     move.w    (a2)+,d0    ;get minimum library version
  292.     cmp.w    LIB_VERSION(a1),d0
  293.     bls    .VersionOK
  294.     addq.l    #6,a2
  295.     bra    .Patch
  296. .VersionOK:
  297.     move.w    (a2)+,d0    ;get offset to new routine
  298.     lea    (a3,d0.w),a0
  299.     move.l    a0,d0    ;new routine address
  300.     move.w    (a2)+,a0    ;_LVO offset
  301.     SYS    SetFunction
  302.     move.w    (a2)+,d1
  303.     move.l    d0,(a5,d1.w)
  304.     bra    .Patch
  305. .EndPatch:
  306.     SYS    Permit
  307.  
  308. ;Create an IORequest structure
  309.     SYS    CreateMsgPort
  310.     move.l    d0,InputMsgPort(a5)
  311.     beq    CleanUp
  312.     move.l    d0,a0
  313.     moveq    #IOSTD_SIZE,d0
  314.     SYS    CreateIORequest
  315.     move.l    d0,InputIORequest(a5)
  316.     beq    CleanUp
  317.  
  318. ;Perform NoClick, if desired.
  319.     move.l    NoClickOption(a5),d2
  320.     beq    .Click
  321.     move.l    d2,a0
  322.     move.l    (a0),d2
  323. .Click:    moveq    #0,d3
  324.     moveq    #3,d4
  325. .ClickLoop:
  326.     lea    TrackName(pc),a0    ;device name
  327.     move.l    d3,d0    ;unit number
  328.     move.l    InputIORequest(a5),a1    ;IO request
  329.     moveq    #0,d1    ;flags
  330.     SYS    OpenDevice
  331.     tst.l    d0
  332.     bne    .ECLoop
  333.     move.l    InputIORequest(a5),a1    ;IO request
  334.     move.l    IO_UNIT(a1),a0
  335.     btst    d3,d2
  336.     beq    .SkipNoClick
  337.     bset    #TDPB_NOCLICK,TDU_PUBFLAGS(a0)
  338. .SkipNoClick:
  339.     tst.l    VerifyOption(a5)
  340.     beq    .NoVerify
  341.     bset    #1,TDU_PUBFLAGS(a0)
  342. .NoVerify:
  343.     tst.l    NoVerifyOption(a5)
  344.     beq    .SkipVerify
  345.     bclr    #1,TDU_PUBFLAGS(a0)
  346. .SkipVerify:
  347.     SYS    CloseDevice
  348. .ECLoop:    addq.l    #1,d3
  349.     dbra    d4,.ClickLoop
  350.  
  351. ;Handle 'STAR' option.
  352.     tst.l    StarOption(a5)
  353.     beq    .NoStar
  354.     move.l    DosBase(a5),a0
  355.     move.l    dl_Root(a0),a0
  356.     bset    #0,rn_Flags(a0)
  357. .NoStar:
  358.  
  359. ;Open the input.device
  360.     lea    InputName(pc),a0    ;device name
  361.     moveq    #0,d0    ;unit number
  362.     move.l    InputIORequest(a5),a1    ;IO request
  363.     moveq    #0,d1    ;flags
  364.     SYS    OpenDevice
  365.     tst.l    d0
  366.     bne    CleanUp
  367.  
  368. ;Install virtical blank routine if needed.
  369.     tst.l    SunMouseOption(a5)
  370.     beq    .SkipVBL
  371.     moveq    #INTB_VERTB,d0
  372.     lea    VBlankServer(a5),a1
  373.     move.l    a5,IS_DATA(a1)
  374.     lea    VBlankRoutine(pc),a0
  375.     move.l    a0,IS_CODE(a1)
  376.     move.b    #NT_INTERRUPT,LN_TYPE(a1)
  377.     SYS    AddIntServer
  378.     bset    #STB_IntInstalled,Status(a5)
  379. .SkipVBL:
  380.  
  381. ;Install input handler
  382.     move.l    InputIORequest(a5),a1
  383.     move.w    #IND_ADDHANDLER,IO_COMMAND(a1)
  384.     lea    InputInterrupt(a5),a0
  385.     move.l    a0,IO_DATA(a1)
  386.     SYS    DoIO
  387.     tst.l    d0
  388.     bne    CleanUp
  389.     st    HandlerInstalled(a5)
  390.  
  391. ;Wait for signal(s)
  392. Wait:
  393.     tst.l    TaskQueue(a5)
  394.     bne    .DoTasks
  395.     lea    Sigs(a5),a0
  396.     move.l    (a0)+,d0
  397.     moveq    #NumSigs-2,d1
  398. ..    add.l    (a0)+,d0
  399.     dbra    d1,..
  400.     move.l    4,a6
  401.     SYS    Wait
  402.     move.l    d0,d7
  403.     move.l    d7,d1
  404.     and.l    QuitSig(a5),d1
  405.     bne    SafeCleanUp
  406.     move.l    d7,d1
  407.     and.l    FuncSig(a5),d1
  408.     beq    Wait
  409. .DoTasks:    move.l    IntBase(a5),a6
  410.     lea    TaskQueue(a5),a4
  411. .TaskLoop:
  412.     move.l    (a4),d0
  413.     beq    Wait
  414.     clr.l    (a4)+
  415.     move.l    d0,a0
  416.     bsr    GetAllSemaphores
  417.     jsr    (a0)
  418.     bsr    FreeAllSemaphores
  419.     bra    .TaskLoop
  420.  
  421. BlankScreenTags:
  422.     dc.l    SA_Depth,1
  423.     dc.l    SA_Colors
  424. reloc4:    dc.l    .ColorSpec-StartAllocCode
  425.     dc.l    0    ;end tags
  426. .ColorSpec:
  427.     dc.w    0,0,0,0
  428.     dc.w    1,0,0,0
  429.     dc.w    -1
  430. BlankScreenWindowTags:
  431.     dc.l    WA_CustomScreen
  432. BlankScreenTagPtr:
  433.     dc.l    0
  434.     dc.l    0    ;end tags
  435.  
  436. DoBlankScreen:
  437.     move.l    BlankScreenPtr(a5),d0
  438.     beq    .Blank
  439.     move.l    d0,a0
  440.     SYS    ScreenToFront
  441.     move.l    BlankScreenWindowPtr(a5),d0
  442.     beq    _RTS1
  443.     move.l    d0,a0
  444.     jmp    _LVOActivateWindow(a6)
  445. .Blank:    sub.l    a0,a0
  446.     lea    BlankScreenTags(pc),a1
  447.     SYS    OpenScreenTagList
  448.     move.l    d0,BlankScreenPtr(a5)
  449.     beq    _RTS1
  450.     lea    BlankScreenTagPtr(pc),a0
  451.     move.l    d0,(a0)
  452.     sub.l    a0,a0
  453.     lea    BlankScreenWindowTags(pc),a1
  454.     SYS    OpenWindowTagList
  455.     move.l    d0,BlankScreenWindowPtr(a5)
  456.     beq    _RTS1
  457.     move.l    d0,a0
  458.     move.l    ChipData(a5),a1
  459. ;    lea    ZeroMouse(a1),a1    ;not needed
  460.     moveq    #1,d0    ;height
  461.     moveq    #16,d1    ;width
  462.     moveq    #0,d2    ;xoffset
  463.     moveq    #0,d3    ;yoffset
  464.     pea    DoBlankScreen(pc)
  465.     move.l    OldSetPointer(a5),-(sp)
  466. _RTS1:    rts
  467.  
  468.  
  469. DoRestoreScreen:
  470.     move.l    BlankScreenPtr(a5),d2
  471.     beq    _RTS1
  472.     clr.l    BlankScreenPtr(a5)
  473.     move.l    BlankScreenWindowPtr(a5),d0
  474.     beq    .SkipWinClose
  475.     clr.l    BlankScreenWindowPtr(a5)
  476.     move.l    d0,a0
  477.     SYS    CloseWindow
  478. .SkipWinClose:
  479.     move.l    d2,a0
  480.     jmp    _LVOCloseScreen(a6)
  481.  
  482.  
  483. CTF:    bsr    GetWindow
  484.     tst.l    d0
  485.     beq    _RTS1
  486.     move.l    CTFOption(a5),a2
  487.     move.l    (a2),d1
  488.     cmp.l    #1,d1
  489.     bhi    .MoreThanOne
  490.     bra    DoWindowToFront
  491. .MoreThanOne:
  492.     cmp.l    ClickWindow(a5),d0
  493.     beq    .SameWindow
  494.     move.l    d0,ClickWindow(a5)
  495.     moveq    #1,d0
  496.     move.l    d0,ClickCount(a5)
  497. .Time:    bsr    GetIBase
  498.     move.l    ib_Seconds(a6),ClickTime+TV_SECS(a5)
  499.     move.l    ib_Micros(a6),ClickTime+TV_MICRO(a5)
  500.     bra    FreeIBase
  501. .SameWindow:
  502.  
  503. ;Check to see whether MaxClickDelay has been exceeded. If not, increment
  504. ;ClickCount and compare with (CTFOption). If equal, do a WindowToFront.
  505. ;Window under pointer in D0.
  506.  
  507.     push    d0
  508.     move.l    ClickTime+TV_SECS(a5),d0
  509.     move.l    ClickTime+TV_MICRO(a5),d1
  510.     bsr    GetIBase
  511.     move.l    ib_Seconds(a6),d2
  512.     move.l    ib_Micros(a6),d3
  513.     bsr    FreeIBase
  514.     SYS    DoubleClick
  515.     tst.l    d0
  516.     beq    .TimeExceeded
  517.     addq.l    #1,ClickCount(a5)
  518.     move.l    CTFOption(a5),a0
  519.     move.l    (a0),d0
  520.     cmp.l    ClickCount(a5),d0
  521.     bhi    .NeedMoreClicks
  522.     clr.l    ClickCount(a5)
  523.     pop    d0
  524.     bra    DoWindowToFront
  525. .TimeExceeded:
  526.     moveq    #1,d0
  527.     move.l    d0,ClickCount(a5)
  528. .NeedMoreClicks:
  529.     pop    d0
  530.     bra    .Time
  531.  
  532. CTB:    bsr    GetWindow
  533.     tst.l    STBOption(a5)
  534.     bne    .FlipScreen
  535.     tst.l    d0
  536.     beq    .FlipScreen
  537.     move.l    d0,a1
  538.     move.l    wd_Flags(a1),d2
  539.     and.l    #WFLG_BACKDROP,d2
  540.     bne    .FlipScreen
  541.  
  542. ;Is this the only window on this screen, except for backdrop windows?
  543.     move.l    wd_WScreen(a1),a1
  544.     move.l    sc_FirstWindow(a1),a1
  545. .BackLoop:
  546.     cmp.l    a1,d0
  547.     beq    .EBackLoop
  548.     move.l    wd_Flags(a1),d2
  549.     and.l    #WFLG_BACKDROP,d2
  550.     beq    .FlipWindow
  551. .EBackLoop:
  552.     move.l    (a1),a1
  553.     move.l    a1,d2
  554.     bne    .BackLoop
  555. .FlipScreen:
  556.     tst.l    d1
  557.     beq    .End
  558.     move.l    d1,a0
  559.     jmp    _LVOScreenToBack(a6)
  560. .FlipWindow:
  561.     move.l    d0,a0
  562.     jmp    _LVOWindowToBack(a6)
  563. .End:    rts
  564.  
  565. PopCLI:
  566. ;Execute the desired command
  567.     move.l    a6,-(sp)
  568.     move.l    DosBase(a5),a6
  569.     move.l    CmdOption(a5),d1
  570.     beq    .End
  571.     lea    .Tags(pc),a0
  572.     move.l    a0,d2    ;tags
  573.  
  574. ;Important fix: free the semaphores (we don't need them here and they can and
  575. ;do lead to deadlocks).
  576.     bsr    FreeAllSemaphores
  577.     SYS    SystemTagList
  578.     bsr    GetAllSemaphores
  579.  
  580.     tst.l    NoWBenchToFrontOption(a5)
  581.     bne    .End
  582.     move.l    IntBase(a5),a6
  583.     SYS    WBenchToFront
  584. .End:    move.l    (sp)+,a6
  585.     rts
  586.  
  587. .Tags:    dc.l    SYS_UserShell,0
  588.     dc.l    NP_Priority,ShellPriority
  589.     dc.l    NP_StackSize
  590. CmdStackSize:
  591.     dc.l    0
  592.     dc.l    0    ;end of tag list
  593.  
  594. SafeCleanUp:
  595. ;Make sure the SetFunction'ed vectors are still intact.
  596.     lea    PatchTable(pc),a0
  597.     move.l    a0,a2
  598. .Safe:    move.w    (a0)+,d0
  599.     beq    CleanUp
  600.     move.l    (a5,d0.w),a1    ;library base
  601.     addq.l    #2,a0    ;skip version #
  602.     move.w    (a0)+,d0
  603.     lea    (a2,d0.w),a3    ;address of new routine
  604.     move.w    (a0)+,d0    ;_LVO offset
  605.     move.w    (a0)+,d1    ;Old vector
  606.     tst.l    (a5,d1.w)
  607.     beq    .Safe
  608.     cmp.l    2(a1,d0.w),a3
  609.     beq    .Safe
  610.  
  611. ;A routine has been patched by another program. Alert the user.
  612. ;a1 is lib pointer, d0.w is routine offset.
  613.  
  614.     ext.l    d0
  615.     neg.l    d0
  616.     move.l    d0,-(sp)
  617.     move.l    LN_NAME(a1),-(sp)
  618.     move.l    sp,a3
  619.     move.l    IntBase(a5),a6
  620.     sub.l    a0,a0
  621.     lea    PatchAlert(pc),a1
  622.     sub.l    a2,a2
  623.     SYS    EasyRequestArgs
  624.     addq.l    #8,sp
  625.     bra    Wait
  626. PatchAlert:
  627.     dc.l    es_SIZEOF
  628.     dc.l    0
  629. reloc1:    dc.l    TitleText-StartAllocCode
  630. reloc2:    dc.l    AlertText-StartAllocCode
  631. reloc3:    dc.l    OkayText-StartAllocCode
  632. TitleText:
  633.     dc.b    'QMouse message',0
  634. AlertText:
  635.     dc.b    'Can''t quit or modify parameters. Another program',$a
  636.     dc.b    'has patched the same OS routines!',$a
  637.     dc.b    $a
  638.     dc.b    'Technical information:',$a
  639.     dc.b    'Library: %s',$a
  640.     dc.b    'Offset:  -$%lx',$a
  641.     dc.b    '(There may be others)',0
  642. OkayText:
  643.     dc.b    'OK',0
  644.     even
  645.  
  646. CleanUp:
  647.  
  648. ;Enter with global ptr in A5
  649.  
  650.     move.l    4,a6
  651.  
  652. ;Remove interrupt routine, if installed.
  653.     btst    #STB_IntInstalled,Status(a5)
  654.     beq    .SkipIntRemove
  655.     moveq    #INTB_VERTB,d0
  656.     lea    VBlankServer(a5),a1
  657.     SYS    RemIntServer
  658. .SkipIntRemove:
  659.  
  660. ;Remove input handler, if installed.
  661.     tst.b    HandlerInstalled(a5)
  662.     beq    .SkipHand
  663.     move.l    InputIORequest(a5),a1
  664.     move.w    #IND_REMHANDLER,IO_COMMAND(a1)
  665.     lea    InputInterrupt(a5),a0
  666.     move.l    a0,IO_DATA(a1)
  667.     SYS    DoIO
  668. .SkipHand:
  669.  
  670.     tst.l    OldCloseScreen(a5)
  671.     beq    .SkipRestore
  672.  
  673.     bsr    RestoreMouse
  674.     move.l    IntBase(a5),a6
  675.     bsr    DoRestoreScreen
  676.     move.l    4,a6
  677.  
  678. ;Restore original vectors.
  679.  
  680.     lea    PatchTable(pc),a2
  681. .RestoreVecs:
  682.     move.w    (a2),d0
  683.     beq    .SkipRestore
  684.     addq.l    #6,a2    ;skip new routine info
  685.     move.l    (a5,d0.w),a1    ;get library base
  686.     move.w    (a2)+,a0    ;get _LVO
  687.     move.w    (a2)+,d0
  688.     move.l    (a5,d0.w),d0    ;old routine
  689.     beq    .RestoreVecs
  690.     SYS    SetFunction
  691.     bra    .RestoreVecs
  692. .SkipRestore:
  693.  
  694. ;Delay for 1/10 second to ensure that no-one is using the patch code.
  695.     move.l    DosBase(a5),d0
  696.     beq    .SkipFreeArg
  697.     move.l    d0,a6
  698.     moveq    #5,d1
  699.     SYS    Delay
  700.  
  701. ;Free argument structure
  702.     move.l    ArgPtr(a5),d1
  703.     beq    .SkipFreeArg
  704.     SYS    FreeArgs
  705. .SkipFreeArg:
  706.  
  707.     move.l    4,a6
  708.  
  709. ;Free signals
  710.     lea    Sigs(a5),a2
  711.     moveq    #NumSigs-1,d2
  712. .SigLoop:    move.l    (a2)+,d1
  713.     beq    .NextSig
  714.     moveq    #-1,d0
  715. .BitLoop:    addq.l    #1,d0
  716.     btst    d0,d1
  717.     beq    .BitLoop
  718.     SYS    FreeSignal
  719. .NextSig:    dbra    d2,.SigLoop
  720.  
  721. ;Remove flicker option, if selected.
  722.     tst.l    FlickerOption(a5)
  723.     beq    .SkipFlicker
  724.     move.l    OriginalCopInit(a5),a0
  725.     move.l    GraphBase(a5),a2
  726.     move.l    gb_copinit(a2),a1
  727. .CLoop:    move.l    (a1)+,(a0)+
  728.     cmp.l    #$008A0000,(a0)
  729.     bne    .CLoop
  730.     move.l    OriginalCopInit(a5),gb_copinit(a2)
  731.     move.l    OriginalCopInit(a5),cop1lc+_custom
  732. .SkipFlicker:
  733.  
  734. ;Close libraries
  735.     lea    LibTable+2(pc),a2
  736.     moveq    #NumLibs-1,d2
  737. .CLibLoop:
  738.     move.w    (a2),a0
  739.     add.l    a5,a0
  740.     tst.l    (a0)
  741.     beq    .SkipClose
  742.     move.l    (a0),a1
  743.     SYS    CloseLibrary
  744. .SkipClose:
  745.     addq.l    #4,a2
  746.     dbra    d2,.CLibLoop
  747.  
  748. ;Close input.device
  749.     move.l    InputIORequest(a5),d0
  750.     beq    .SkipCloseDev
  751.     move.l    d0,a1
  752.     tst.b    IO_ERROR(a1)    ;was there an error?
  753.     bne    .SkipCloseDev    ;yes, don't close
  754.     SYS    CloseDevice
  755. .SkipCloseDev:
  756.  
  757. ;Delete IORequest structure
  758.     move.l    InputIORequest(a5),a0
  759.     SYS    DeleteIORequest
  760.     move.l    InputMsgPort(a5),a0
  761.     SYS    DeleteMsgPort
  762.  
  763. ;Free chip data.
  764.     move.l    ChipData(a5),d0
  765.     beq    .SkipChipData
  766.     move.l    d0,a1
  767.     move.l    #CData_Sizeof,d0
  768.     SYS    FreeMem
  769. .SkipChipData:
  770.  
  771. ;Deallocate global structure. Note that this code is (sometimes) executed
  772. ;within the memory that we are freeing, so we are careful to terminate with
  773. ;a JMP.
  774.     move.l    a5,a1
  775.     move.l    #Data_Sizeof,d0
  776.     jmp    _LVOFreeMem(a6)
  777.  
  778. ;Semaphore routines
  779.  
  780. GetIBase:
  781. ;    PUTDEBUG    <'GetIBase: Called'>
  782.     movem.l    d0-d1/a0-a1/a5-a6,-(sp)
  783.     move.l    GlobalPtr(pc),a5
  784.     move.l    IntBase(a5),a6
  785.     moveq    #0,d0
  786.     SYS    LockIBase
  787.     move.l    d0,IBaseLock(a5)
  788.     movem.l    (sp)+,d0-d1/a0-a1/a5-a6
  789. ;    PUTDEBUG    <'GetIBase: Done'>
  790.     rts
  791. FreeIBase:
  792. ;    PUTDEBUG    <'FreeIBase'>
  793.     movem.l    d0-d1/a0-a1/a6,-(sp)
  794.     move.l    GlobalPtr(pc),a0
  795.     move.l    IntBase(a0),a6
  796.     move.l    IBaseLock(a0),a0
  797.     SYS    UnlockIBase
  798.     movem.l    (sp)+,d0-d1/a0-a1/a6
  799.     rts
  800.  
  801.  
  802. GetSemaphore:
  803.     PUTDEBUG    <'GetSemaphore: Called'>
  804.     movem.l    a0/a6,-(sp)
  805.     move.l    GlobalPtr(pc),a0
  806.     lea    MySemaphore(a0),a0
  807. _GS:    move.l    4,a6
  808.     SYS    ObtainSemaphore
  809.     movem.l    (sp)+,a0/a6
  810.     PUTDEBUG    <'GetSemaphore: Done'>
  811.     rts
  812. FreeSemaphore:
  813.     movem.l    a0/a6,-(sp)
  814.     move.l    GlobalPtr(pc),a0
  815.     lea    MySemaphore(a0),a0
  816. _FS:    move.l    4,a6
  817.     SYS    ReleaseSemaphore
  818.     movem.l    (sp)+,a0/a6
  819.     PUTDEBUG    <'FreeSemaphore'>
  820.     rts
  821.  
  822. GetCloseWindowSemaphore:
  823.     PUTDEBUG    <'GetCloseWindowSemaphore'>
  824.     movem.l    a0/a6,-(sp)
  825.     move.l    GlobalPtr(pc),a0
  826.     lea    CloseWindowSemaphore(a0),a0
  827.     bra    _GS
  828. FreeCloseWindowSemaphore:
  829.     PUTDEBUG    <'FreeCloseWindowSemaphore'>
  830.     movem.l    a0/a6,-(sp)
  831.     move.l    GlobalPtr(pc),a0
  832.     lea    CloseWindowSemaphore(a0),a0
  833.     bra    _FS
  834.  
  835. GetCloseScreenSemaphore:
  836.     PUTDEBUG    <'GetCloseScreenSemaphore'>
  837.     movem.l    a0/a6,-(sp)
  838.     move.l    GlobalPtr(pc),a0
  839.     lea    CloseScreenSemaphore(a0),a0
  840.     bra    _GS
  841. FreeCloseScreenSemaphore:
  842.     PUTDEBUG    <'FreeCloseScreenSemaphore'>
  843.     movem.l    a0/a6,-(sp)
  844.     move.l    GlobalPtr(pc),a0
  845.     lea    CloseScreenSemaphore(a0),a0
  846.     bra    _FS
  847.  
  848. GetCloseWBSemaphore:
  849.     PUTDEBUG    <'GetCloseWBSemaphore'>
  850.     movem.l    a0/a6,-(sp)
  851.     move.l    GlobalPtr(pc),a0
  852.     lea    CloseWBSemaphore(a0),a0
  853.     bra    _GS
  854. FreeCloseWBSemaphore:
  855.     PUTDEBUG    <'FreeCloseWBSemaphore'>
  856.     movem.l    a0/a6,-(sp)
  857.     move.l    GlobalPtr(pc),a0
  858.     lea    CloseWBSemaphore(a0),a0
  859.     bra    _FS
  860.  
  861. GetAllSemaphores:
  862. ;The order matters! The sems must be allocated in this order to avoid
  863. ;the "deadly embrace".
  864.     bsr    GetCloseWBSemaphore
  865.     bsr    GetCloseScreenSemaphore
  866.     bsr    GetCloseWindowSemaphore
  867.     bra    GetSemaphore
  868. FreeAllSemaphores:
  869. ;We can free in any order (provided that we are freeing ALL of them).
  870.     bsr    FreeSemaphore
  871.     bsr    FreeCloseWindowSemaphore
  872.     bsr    FreeCloseScreenSemaphore
  873.     bra    FreeCloseWBSemaphore
  874.  
  875.  
  876. LibTable:    dc.w    DosName-LibTable
  877.     dc.w    DosBase
  878.     dc.w    IntName-LibTable
  879.     dc.w    IntBase
  880.     dc.w    LayersName-LibTable
  881.     dc.w    LayersBase
  882.     dc.w    GraphName-LibTable
  883.     dc.w    GraphBase
  884.     dc.w    UtilityName-LibTable
  885.     dc.w    _UtilityBase
  886. EndLibTable:
  887.  
  888. NumLibs    equ    (EndLibTable-LibTable)/4
  889.  
  890. ;****************** SetFunction'ed routines ***************
  891.  
  892. patch    macro
  893.     dc.w    \1
  894.     dc.w    \3    ;minimum library version
  895.     dc.w    New\2-PatchTable
  896.     dc.w    _LVO\2
  897.     dc.w    Old\2
  898.     endm
  899.  
  900. PatchTable:
  901.     patch    IntBase,SetWindowPointerA,39
  902.     patch    IntBase,OpenWindowTagList,39
  903.     patch    IntBase,CloseScreen,37
  904.     patch    IntBase,CloseWorkBench,37
  905.     patch    IntBase,CloseWindow,37
  906.     patch    IntBase,SetPointer,37
  907.     patch    IntBase,ClearPointer,37
  908.     patch    IntBase,DisplayBeep,37
  909.     dc.w    0
  910.  
  911. NewDisplayBeep:
  912.     PUTDEBUG    <'NewDisplayBeep'>
  913.     move.l    GlobalPtr(pc),a1
  914.     tst.l    BeepOption(a1)
  915.     bne    .SkipBeep
  916.     move.l    OldDisplayBeep(a1),-(sp)
  917. .SkipBeep:
  918.     rts
  919.  
  920. NewOpenWindowTagList:
  921. ;Enter with NewWindow in A0, taglist in A1
  922.     PUTDEBUG    <'NewOpenWindowTagList'>
  923.     move.l    a1,-(sp)
  924.     pea    .HandlePointer(pc)
  925.     subq.l    #8,sp
  926.     move.l    a0,(sp)
  927.     move.l    GlobalPtr(pc),a0
  928.     move.l    OldOpenWindowTagList(a0),4(sp)
  929.     move.l    (sp)+,a0
  930. .End:    rts
  931. .RestoreD0:
  932.     move.l    (sp)+,d0
  933.     rts
  934. .HandlePointer:
  935.     move.l    (sp)+,a1
  936.     tst.l    d0
  937.     beq    .End
  938.     move.l    d0,a0
  939.     move.l    d0,-(sp)
  940.     pea    .RestoreD0(pc)
  941. ;    bra    NewSetWindowPointerA
  942.  
  943. NewSetWindowPointerA:
  944. ;Enter with:
  945. ;A0 - Window
  946. ;A1 - taglist
  947.  
  948. SaveRegs    setrl    d4-d5/a0-a6
  949.  
  950.     PUTDEBUG    <'NewSetWindowPointerA'>
  951.     bsr    GetSemaphore
  952.     movem.l    SaveRegs,-(sp)
  953.     move.l    GlobalPtr(pc),a5
  954.     lea    PointerList(a5),a2
  955.  
  956. ;Find if window is already in table and find empty spot.
  957.     moveq    #POINTERLISTSIZE-1,d4
  958.     sub.l    a3,a3
  959. .WinSearch:
  960.     move.l    pt_Window(a2),d5
  961.     bne    .SkipSave
  962.     move.l    a2,a3
  963. .SkipSave:
  964.     cmp.l    d5,a0
  965.     beq    .Found
  966.     lea    pt_Sizeof(a2),a2
  967.     dbra    d4,.WinSearch
  968.     move.l    a3,a2
  969.     move.l    a2,d4
  970.     beq    .CallOld    ;no room in table, so forget it
  971. .Found:
  972. ;Store the taglist information
  973.     move.l    a0,a3    ;window
  974.     move.l    a1,a4    ;taglist
  975.     move.l    a0,pt_Window(a2)
  976.     st    TagVersion(a2)
  977.     move.l    _UtilityBase(a5),a6
  978. ;Check for WA_BusyPointer.
  979.     move.l    #WA_BusyPointer,d0
  980.     move.l    a4,a0
  981.     SYS    FindTagItem
  982.     tst.l    d0
  983.     beq    .NotBusy
  984.     move.l    d0,a0
  985.  
  986.     IFNE    INFO_LEVEL
  987.     move.l    4(a0),-(sp)
  988.     move.l    (a0),-(sp)
  989.     PUTDEBUG    <'WA_BusyPointer=%lx,%lx '>
  990.     addq.l    #8,sp
  991.     ENDC
  992.  
  993.     move.l    (a0),(a2)
  994.     move.l    4(a0),4(a2)
  995.     beq    .NotBusy
  996.     clr.l    8(a2)
  997.     bra    .CallOld
  998. .NotBusy:
  999. ;Check for WA_Pointer.
  1000.     move.l    #WA_Pointer,d0
  1001.     move.l    a4,a0
  1002.     SYS    FindTagItem
  1003.     tst.l    d0
  1004.     beq    .Nothing
  1005.     move.l    d0,a0
  1006.  
  1007.     IFNE    INFO_LEVEL
  1008.     move.l    4(a0),-(sp)
  1009.     move.l    (a0),-(sp)
  1010.     PUTDEBUG    <'WA_Pointer=%lx,%lx '>
  1011.     addq.l    #8,sp
  1012.     ENDC
  1013.  
  1014.     move.l    (a0),(a2)
  1015.     move.l    4(a0),4(a2)
  1016.     clr.l    8(a2)
  1017.     bra    .CallOld
  1018. .Nothing:
  1019. ;Don't understand the taglist.
  1020.     PUTDEBUG    <'Don''t grok SetWindowPointerA taglist!'>
  1021.     clr.l    pt_Window(a2)
  1022. .CallOld:    cmp.l    MBlankWindow(a5),a3
  1023.     beq    .End
  1024. ;Call old SetWindowPointerA
  1025.     movem.l    (sp)+,SaveRegs
  1026.     subq.l    #8,sp
  1027.     move.l    a0,(sp)
  1028.     move.l    GlobalPtr(pc),a0
  1029.     move.l    OldSetWindowPointerA(a0),4(sp)
  1030.     move.l    (sp)+,a0
  1031.     bra    FreeSemaphore
  1032. .End:    movem.l    (sp)+,SaveRegs
  1033.     bra    FreeSemaphore
  1034.  
  1035. NewSetPointer:
  1036.     PUTDEBUG    <'NewSetPointer'>
  1037.     bsr    GetSemaphore
  1038.     movem.l    d4-d5/a2-a3/a5,-(sp)
  1039.     move.l    GlobalPtr(pc),a5
  1040.     cmp.l    ChipData(a5),a1    ;special check to ward off sneaky code like
  1041.     beq    .End1        ;reqtools
  1042.     lea    PointerList(a5),a2
  1043.  
  1044. ;Find if window is already in table and find empty spot.
  1045.     moveq    #POINTERLISTSIZE-1,d4
  1046.     sub.l    a3,a3
  1047. .WinSearch:
  1048.     move.l    pt_Window(a2),d5
  1049.     bne    .SkipSave
  1050.     move.l    a2,a3
  1051. .SkipSave:
  1052.     cmp.l    d5,a0
  1053.     beq    .Found
  1054.     lea    pt_Sizeof(a2),a2
  1055.     dbra    d4,.WinSearch
  1056.     move.l    a3,a2
  1057.     move.l    a2,d4
  1058.     beq    .End    ;no room in table, so forget it
  1059. .Found:    movem.l    d0-d3/a0-a1,(a2)
  1060.     clr.b    TagVersion(a2)
  1061. .End:    cmp.l    MBlankWindow(a5),a0
  1062.     beq    .End1
  1063.     movem.l    (sp)+,d4-d5/a2-a3/a5
  1064.     subq.l    #8,sp
  1065.     move.l    a0,(sp)
  1066.     move.l    GlobalPtr(pc),a0
  1067.     move.l    OldSetPointer(a0),4(sp)
  1068.     move.l    (sp)+,a0
  1069.     bra    FreeSemaphore
  1070. .End1:    movem.l    (sp)+,d4-d5/a2-a3/a5
  1071.     bra    FreeSemaphore
  1072.  
  1073. NewClearPointer:
  1074.     PUTDEBUG    <'NewClearPointer'>
  1075.     bsr    GetSemaphore
  1076.     move.l    GlobalPtr(pc),a1
  1077.     lea    PointerList(a1),a1
  1078.     moveq    #POINTERLISTSIZE-1,d0
  1079. .ClearLoop:
  1080.     cmp.l    pt_Window(a1),a0
  1081.     beq    .Found
  1082.     lea    pt_Sizeof(a1),a1
  1083.     dbra    d0,.ClearLoop
  1084.     bra    .End
  1085. .Found:    clr.l    pt_Window(a1)
  1086. .End:    move.l    GlobalPtr(pc),a1
  1087.     cmp.l    MBlankWindow(a1),a0
  1088.     beq    .End1
  1089.     move.l    OldClearPointer(a1),-(sp)
  1090. .End1:    bra    FreeSemaphore
  1091.  
  1092. NewCloseWorkBench:
  1093.     PUTDEBUG    <'NewCloseWorkBench'>
  1094.     bsr    GetCloseWBSemaphore
  1095.     SYS    OpenWorkBench    ;get workbench screen ptr in d0
  1096.     tst.l    d0
  1097.     beq    FreeCloseWBSemaphore
  1098.     move.l    d0,a0
  1099.     move.l    GlobalPtr(pc),a1
  1100.     move.l    OldCloseWorkBench(a1),d1
  1101.     pea    .Free(pc)
  1102.     bra    CloseScreenCode
  1103. .Free:    bra    FreeCloseWBSemaphore
  1104.  
  1105. NewCloseScreen:
  1106.     PUTDEBUG    <'NewCloseScreen'>
  1107.     bsr    GetCloseScreenSemaphore
  1108.     move.l    GlobalPtr(pc),a1
  1109.     move.l    OldCloseScreen(a1),d1
  1110.     pea    .Free(pc)
  1111.     bra    CloseScreenCode
  1112. .Free:    bra    FreeCloseScreenSemaphore
  1113.  
  1114. CloseScreenCode:
  1115. ;Code shared by NewCloseScreen and NewCloseWorkBench
  1116. ;Enter with Screen in A0, Global in A1, old vector in D1
  1117.  
  1118.     bsr    GetSemaphore
  1119.     lea    ScreenList(a1),a1
  1120.     moveq    #SCREENLISTSIZE-1,d0
  1121. .Loop:    cmp.l    (a1),a0
  1122.     beq    .Match
  1123.     addq.l    #8,a1
  1124.     dbra    d0,.Loop
  1125. .End:    bsr    FreeSemaphore
  1126.     move.l    GlobalPtr(pc),a1
  1127.     pea    .ExtraClose(pc)
  1128.     move.l    d1,-(sp)
  1129.     rts
  1130. .Match:    clr.l    (a1)
  1131.     bra    .End
  1132. .ExtraClose:
  1133.     move.l    GlobalPtr(pc),a0
  1134.     bsr    GetIBase
  1135.     move.l    ib_FirstScreen(a6),CurrentTopScreen(a0)
  1136.     move.l    ib_ActiveScreen(a6),CurrentActiveScreen(a0)
  1137.     bsr    FreeIBase
  1138.     bra    RestoreWindow
  1139.  
  1140. NewCloseWindow:
  1141.     PUTDEBUG    <'NewCloseWindow'>
  1142.     move.l    GlobalPtr(pc),a1
  1143.     bsr    GetCloseWindowSemaphore
  1144.     bsr    GetSemaphore
  1145.     pea    .ExtraClose(pc)
  1146.     push    a0
  1147.     SYS    ClearPointer
  1148.     pop    a0
  1149.     move.l    GlobalPtr(pc),a1
  1150.     cmp.l    MBlankWindow(a1),a0
  1151.     bne    .SkipClearMBW
  1152.     clr.l    MBlankWindow(a1)
  1153. .SkipClearMBW:
  1154.     cmp.l    ClickWindow(a1),a0
  1155.     bne    .SkipClearCW
  1156.     clr.l    ClickWindow(a1)
  1157. .SkipClearCW:
  1158.     lea    ScreenList+4(a1),a1
  1159.     moveq    #SCREENLISTSIZE-1,d0
  1160. .Loop:    cmp.l    (a1),a0
  1161.     beq    .Match
  1162.     addq.l    #8,a1
  1163.     dbra    d0,.Loop
  1164. .End:    bsr    FreeSemaphore
  1165.     move.l    GlobalPtr(pc),a1
  1166.     move.l    OldCloseWindow(a1),-(sp)
  1167.     rts
  1168. .Match:    clr.l    -4(a1)
  1169.     bra    .End
  1170. .ExtraClose:
  1171.     move.l    GlobalPtr(pc),a0
  1172.     bsr    GetIBase
  1173.     move.l    ib_ActiveWindow(a6),CurrentActiveWindow(a0)
  1174.     bsr    FreeIBase
  1175.     bra    FreeCloseWindowSemaphore
  1176.  
  1177. ;****************** End of SetFunction'ed routines ***************
  1178.  
  1179. RememberWindow:
  1180.  
  1181. ;No OS calls
  1182. ;Enter with Screen in A0, Window in A2
  1183.  
  1184.     movem.l    d0-d1/a0-a2/a5,-(sp)
  1185.     move.l    GlobalPtr(pc),a5
  1186.  
  1187. ;Sanity checks
  1188.     move.l    a0,d0
  1189.     beq    .End
  1190.     move.l    a2,d0
  1191.     beq    .End
  1192.  
  1193.     lea    ScreenList(a5),a1
  1194.     moveq    #SCREENLISTSIZE-1,d0
  1195. .ScLoop:    cmp.l    (a1),a0
  1196.     beq    .Match
  1197.     addq.l    #8,a1
  1198.     dbra    d0,.ScLoop
  1199.  
  1200. ;Screen not found. Add to screen list.
  1201.     lea    ScreenList(a5),a1
  1202.     moveq    #SCREENLISTSIZE-1,d0
  1203. .AddLoop:    tst.l    (a1)
  1204.     beq    .Match
  1205.     addq.l    #8,a1
  1206.     dbra    d0,.AddLoop
  1207.     bra    .End    ;table is full
  1208. .Match:
  1209.     move.l    a0,(a1)+    ;screen
  1210.     move.l    a2,(a1)    ;currently activated window
  1211. .End:    movem.l    (sp)+,d0-d1/a0-a2/a5
  1212.     rts
  1213.  
  1214. RestoreWindow:
  1215.     movem.l    a1-a2,-(sp)
  1216.     move.l    GlobalPtr(pc),a1
  1217.     lea    TaskRestoreWindow(pc),a2
  1218.     bsr    DoFunc
  1219.     movem.l    (sp)+,a1-a2
  1220.     rts
  1221.  
  1222. TaskRestoreWindow:
  1223.  
  1224. ;This routine restores (re-activates) the previously activated window for
  1225. ;this screen.
  1226.  
  1227.     movem.l    d0-d2/a0-a2/a6,-(sp)
  1228.     move.l    GlobalPtr(pc),a0
  1229.     tst.l    NoActivateOption(a0)
  1230.     bne    .End
  1231.     lea    ScreenList(a0),a2
  1232.     move.l    IntBase(a0),a6
  1233.     bsr    GetIBase
  1234.     move.l    ib_FirstScreen(a6),d2
  1235.     bsr    FreeIBase
  1236.     tst.l    d2
  1237.     beq    .End    ;sanity check
  1238.     move.l    d2,CurrentTopScreen(a0)
  1239.     tst.l    PubChangeOption(a0)
  1240.     beq    .NoPubChange
  1241.  
  1242. ;If the screen is public, make it the default public screen.
  1243.  
  1244.     SYS    LockPubScreenList
  1245. .PubLoop:    tst.l    d0
  1246.     beq    .EndPubChange
  1247.     move.l    d0,a0
  1248.     cmp.l    psn_Screen(a0),d2
  1249.     beq    .FoundScreen
  1250.     move.l    LN_SUCC(a0),d0
  1251.     bra    .PubLoop    
  1252. .FoundScreen:
  1253.     move.l    LN_NAME(a0),a0
  1254.     SYS    SetDefaultPubScreen
  1255.  
  1256. .EndPubChange:
  1257.     SYS    UnlockPubScreenList
  1258. .NoPubChange:
  1259.     move.l    d2,a0
  1260.     moveq    #SCREENLISTSIZE-1,d0
  1261. .Loop:    cmp.l    (a2),a0
  1262.     beq    .Match
  1263.     addq.l    #8,a2
  1264.     dbra    d0,.Loop
  1265.     move.l    sc_FirstWindow(a0),a0    ;default window
  1266.     move.l    a0,d0
  1267.     beq    .End    ;sanity check
  1268.     bra    .SkipMatch
  1269. .Match:
  1270.     move.l    4(a2),a0
  1271. .SkipMatch:
  1272.     SYS    ActivateWindow
  1273.     move.l    GlobalPtr(pc),a0
  1274.     bsr    GetIBase
  1275.     move.l    ib_ActiveScreen(a6),CurrentActiveScreen(a0)
  1276.     bsr    FreeIBase
  1277. .End:    movem.l    (sp)+,d0-d2/a0-a2/a6
  1278.     rts
  1279.  
  1280.  
  1281. ;Get window associated with current mouse position.
  1282. ;Returns Window in D0 and screen in D1.
  1283.  
  1284. GetWindow:
  1285.     movem.l    d4/a0-a1/a4-a6,-(sp)
  1286.     move.l    GlobalPtr(pc),a5
  1287.     move.l    LayersBase(a5),a6
  1288.     move.l    IntBase(a5),a4
  1289.     bsr    GetIBase
  1290.     move.l    ib_FirstScreen(a4),d4
  1291. .ScLoop:    tst.l    d4
  1292.     beq    .ErrEnd
  1293.     move.l    d4,a0
  1294.     move.l    sc_NextScreen(a0),d4
  1295.     move.w    sc_MouseX(a0),d0
  1296.     bmi    .ScLoop
  1297.     move.w    sc_MouseY(a0),d1
  1298.     bmi    .ScLoop
  1299.     push    a0
  1300.     lea    sc_LayerInfo(a0),a0
  1301.     bsr    FreeIBase
  1302.     SYS    WhichLayer
  1303.     pop    d1
  1304.     tst.l    d0
  1305.     beq    .End
  1306.     move.l    d0,a0
  1307.     move.l    lr_Window(a0),d0
  1308. .End:    movem.l    (sp)+,d4/a0-a1/a4-a6
  1309.     rts
  1310. .ErrEnd:    bsr    FreeIBase
  1311.     moveq    #0,d0
  1312.     moveq    #0,d1
  1313.     bra    .End
  1314.  
  1315. ActivateWindow:
  1316.  
  1317. ;Activate the window under the mouse pointer.
  1318. ;Enter with IntuitionBase in A6
  1319.  
  1320.     bsr    GetWindow
  1321.     tst.l    d0
  1322.     beq    .End
  1323.     move.l    d0,a0
  1324.     bsr    GetIBase
  1325.     move.l    ib_ActiveWindow(a6),d0
  1326.     bsr    FreeIBase
  1327.     cmp.l    d0,a0
  1328.     beq    .End
  1329.     tst.l    wd_FirstRequest(a0)
  1330.     bne    .End
  1331.     SYS    ActivateWindow
  1332. .End:    rts
  1333.  
  1334. DoWindowToFront:
  1335.  
  1336. ;Perform a WindowToFront on the window in D0.
  1337. ;Enter with IntuitionBase in A6.
  1338.  
  1339.     tst.l    d0
  1340.     beq    .End1
  1341.     movem.l    d0-d1/a0-a1/a6,-(sp)
  1342.     move.l    d0,a0
  1343.     move.l    wd_WLayer(a0),a1
  1344.     move.l    a1,d0
  1345.     beq    .End
  1346.     move.l    lr_ClipRect(a1),a1
  1347.     move.l    a1,d0
  1348.     beq    .End
  1349.     tst.l    (a1)
  1350.     beq    .End
  1351.     move.l    wd_Flags(a0),d0
  1352.     and.l    #WFLG_BACKDROP,d0
  1353.     bne    .End
  1354.     SYS    WindowToFront
  1355. .End:    movem.l    (sp)+,d0-d1/a0-a1/a6
  1356. .End1:    rts
  1357.  
  1358. BlankMouse:
  1359.     movem.l    d0-d3/a0-a1/a5-a6,-(sp)
  1360.     move.l    GlobalPtr(pc),a5
  1361.     move.l    IntBase(a5),a6
  1362.     bsr    GetIBase
  1363.     move.l    ib_ActiveWindow(a6),d0
  1364.     bsr    FreeIBase
  1365.     tst.l    d0
  1366.     beq    .End
  1367.     cmp.l    MBlankWindow(a5),d0
  1368.     beq    .End
  1369.     bsr    RestoreMouse
  1370.     move.l    d0,MBlankWindow(a5)
  1371.     move.l    d0,a0
  1372.     move.l    ChipData(a5),a1
  1373. ;    lea    ZeroMouse(a1),a1    ;not needed
  1374.     moveq    #1,d0    ;height
  1375.     moveq    #16,d1    ;width
  1376.     moveq    #0,d2    ;xoffset
  1377.     moveq    #0,d3    ;yoffset
  1378.     pea    .End(pc)
  1379.     move.l    OldSetPointer(a5),-(sp)
  1380.     rts
  1381. .End:    movem.l    (sp)+,d0-d3/a0-a1/a5-a6
  1382.     rts
  1383.  
  1384. RestoreMouse:
  1385.     movem.l    d0-d1/a0-a2/a5-a6,-(sp)
  1386.     move.l    GlobalPtr(pc),a5
  1387.     move.l    IntBase(a5),a6
  1388.     move.l    MBlankWindow(a5),d0
  1389.     beq    .End
  1390.  
  1391. ;Look for window in pointer table. If present, do a SetPointer or SetWindowPointerA
  1392. ;to restore the custom pointer. Otherwise call ClearPointer.
  1393.  
  1394.     move.l    d0,a0
  1395.     clr.l    MBlankWindow(a5)
  1396.     lea    PointerList(a5),a1
  1397.     moveq    #POINTERLISTSIZE-1,d0
  1398. .WinLoop:    cmp.l    pt_Window(a1),a0
  1399.     beq    .Found
  1400.     lea    pt_Sizeof(a1),a1
  1401.     dbra    d0,.WinLoop
  1402.     pea    .End(pc)
  1403.     move.l    OldClearPointer(a5),-(sp)
  1404.     rts
  1405. .End:    movem.l    (sp)+,d0-d1/a0-a2/a5-a6
  1406.     rts
  1407. .Found:    move.l    a1,a2
  1408.     tst.b    TagVersion(a2)
  1409.     beq    .NoTag
  1410. ;Call SetWindowPointerA to restore the custom pointer.
  1411.     move.l    pt_Window(a2),a0
  1412.     pea    .End(pc)
  1413.     move.l    OldSetWindowPointerA(a5),-(sp)
  1414.     rts
  1415. .NoTag:    movem.l    (a2),d0-d3/a0-a1
  1416.     pea    .End(pc)
  1417.     move.l    OldSetPointer(a5),-(sp)
  1418.     rts
  1419.  
  1420. ;***************************************************************************
  1421. ;Start of input handler code
  1422. ;***************************************************************************
  1423.  
  1424. BlankScreen:
  1425.  
  1426. ;Enter with global in A1.
  1427.     bset    #STB_SBlanked,Status(a1)
  1428.     lea    DoBlankScreen(pc),a2
  1429.     bra    DoFunc
  1430.  
  1431. RestoreScreen:
  1432.  
  1433. ;Enter with global in A1 AND input event in A0.
  1434.     move.l    ie_TimeStamp(a0),ScreenTime(a1)
  1435.     bclr    #STB_SBlanked,Status(a1)
  1436.     beq    _RTS
  1437.     lea    DoRestoreScreen(pc),a2
  1438. ;    bra    DoFunc
  1439.  
  1440. DoFunc:
  1441.  
  1442. ;Enter with pointer to routine in A2
  1443. ;Enter with global ptr in A1.
  1444.  
  1445.     movem.l    d0-d1/a0-a1/a6,-(sp)
  1446.     lea    TaskQueue(a1),a0
  1447.     moveq    #MAXQUEUE-1,d0
  1448. ..    tst.l    (a0)+
  1449.     dbeq    d0,..
  1450.     bne    .End
  1451.     move.l    a2,-(a0)
  1452.     move.l    FuncSig(a1),d0
  1453.     move.l    Task(a1),a1
  1454.     move.l    4,a6
  1455.     SYS    Signal
  1456. .End:    movem.l    (sp)+,d0-d1/a0-a1/a6
  1457. _RTS:    rts
  1458.  
  1459. ;**************************** Input handler *********************************
  1460.  
  1461. IntRoutine:
  1462.     movem.l    d2/a2/a6,-(sp)
  1463.     move.l    a0,-(sp)
  1464.     move.l    IntBase(a1),a6
  1465.     bsr    GetIBase
  1466.  
  1467. ;Handle NoFlicker option
  1468.     tst.l    FlickerOption(a1)
  1469.     beq    .SkipFlick
  1470.     move.l    GraphBase(a1),a0
  1471.     move.l    gb_LOFlist(a0),a2
  1472.     move.l    WaitLineAddress(a1),a0
  1473.     cmp.b    #WaitLine-1,WindowStart(a2)
  1474.     blo    .DisableNF
  1475.     move.b    #WaitLine,(a0)
  1476.     bra    .SkipDisableNF
  1477. .DisableNF:
  1478.     clr.b    (a0)
  1479. .SkipDisableNF:
  1480.     move.l    GraphBase(a1),a0
  1481.     move.l    gb_copinit(a0),a0
  1482.     cmp.w    #color,SysBackground-2(a0)
  1483.     bne    .DefColor
  1484.     move.w    SysBackground(a0),d0
  1485.     move.l    RealBackground(a1),a0
  1486.     move.w    d0,(a0)
  1487.     bra    .SkipColor
  1488. .DefColor:
  1489.     move.l    RealBackground(a1),a0
  1490.     move.w    #DefColor,(a0)
  1491. .SkipColor:
  1492.     move.l    (sp),a0
  1493. .SkipFlick:
  1494.  
  1495. ;Check for change in active screen.
  1496. ;But first: attempt to obtain the semaphores
  1497.     movem.l    a0-a1/a6,-(sp)
  1498.     move.l    4,a6
  1499.     lea    Semaphores(a1),a2
  1500.     moveq    #NumSemaphores-1,d2
  1501. .Attempt:    move.l    a2,a0
  1502.     SYS    AttemptSemaphore
  1503.     tst.l    d0
  1504.     beq    .AttemptFailed
  1505.     lea    SS_SIZE(a2),a2
  1506.     dbra    d2,.Attempt
  1507.     movem.l    (sp)+,a0-a1/a6
  1508.     bra    .CheckScreenStuff
  1509. .AttemptFailed:
  1510.     moveq    #2,d0
  1511.     sub.w    d2,d0
  1512.     bmi    .NoneSucceeded
  1513.     move.l    a2,a0
  1514. .CleanUp:    lea    -SS_SIZE(a0),a0
  1515.     SYS    ReleaseSemaphore
  1516.     dbra    d0,.CleanUp
  1517. .NoneSucceeded:
  1518.     movem.l    (sp)+,a0-a1/a6
  1519.     bra    .NoSemaphore
  1520.  
  1521. .CheckScreenStuff:
  1522.     move.l    CurrentActiveScreen(a1),d0
  1523.     cmp.l    ib_ActiveScreen(a6),d0
  1524.     beq    .SameActiveScreen
  1525.     push    a0
  1526.     move.l    CurrentActiveScreen(a1),a0
  1527.     move.l    CurrentActiveWindow(a1),a2
  1528.     bsr    RememberWindow
  1529.     pop    a0
  1530. .SameActiveScreen:
  1531.  
  1532. ;Check for change in top screen.
  1533.     move.l    CurrentTopScreen(a1),d0
  1534.     beq    .CSZ
  1535.     cmp.l    ib_FirstScreen(a6),d0
  1536.     beq    .SkipRW
  1537.     push    a0
  1538.     move.l    CurrentActiveScreen(a1),a0
  1539.     move.l    CurrentActiveWindow(a1),a2
  1540.     bsr    RememberWindow
  1541.     pop    a0
  1542.     lea    TaskRestoreWindow(pc),a2
  1543.     bsr    DoFunc
  1544. .CSZ:    move.l    ib_FirstScreen(a6),CurrentTopScreen(a1)
  1545. .SkipRW:    move.l    ib_ActiveWindow(a6),CurrentActiveWindow(a1)
  1546.     move.l    ib_ActiveScreen(a6),CurrentActiveScreen(a1)
  1547.     bsr    FreeAllSemaphores
  1548. .NoSemaphore:
  1549.  
  1550. ;If screen is blanked, re-blank (actually just move the blanking screen to the
  1551. ;front)
  1552.     btst    #STB_SBlanked,Status(a1)
  1553.     beq    .SkipReBlank
  1554.     move.l    ib_FirstScreen(a6),d0
  1555.     cmp.l    BlankScreenPtr(a1),d0
  1556.     beq    .SkipReBlank
  1557.     bsr    BlankScreen
  1558. .SkipReBlank:
  1559.  
  1560. ;Re-blank mouse if a new window has been activated.
  1561.     move.l    MBlankWindow(a1),d0
  1562.     beq    .Loop
  1563.     cmp.l    ib_ActiveWindow(a6),d0
  1564.     beq    .EndMBW
  1565.     lea    BlankMouse(pc),a2
  1566.     bsr    DoFunc
  1567. .EndMBW:
  1568.  
  1569. .Loop:    cmp.b    #IECLASS_TIMER,ie_Class(a0)
  1570.     beq    .Timer
  1571.  
  1572.     cmp.b    #IECLASS_RAWKEY,ie_Class(a0)
  1573.     bne    .NotKey
  1574.     tst.b    ie_Code+1(a0)
  1575.     bmi    .Next    ;ignore up key codes
  1576.  
  1577.     bsr    RestoreScreen
  1578.  
  1579. ;Handle immediate blank feature
  1580.     tst.l    ImmBlankOption(a1)
  1581.     beq    .SkipImmBlank
  1582. ;Check for lamiga+ramiga
  1583.     cmp.b    #IEQUALIFIER_LCOMMAND+IEQUALIFIER_RCOMMAND,ie_Qualifier+1(a0)
  1584.     bne    .SkipImmBlank
  1585.     bsr    BlankScreen
  1586. .SkipImmBlank:
  1587.  
  1588. ;Perform SunKey
  1589.     tst.l    SunKeyOption(a1)
  1590.     beq    .SkipSKey
  1591.     lea    ActivateWindow(pc),a2
  1592.     bsr    DoFunc
  1593. .SkipSKey:
  1594.  
  1595. ;Do Northgate keyboard mapping.
  1596.     tst.l    NorthGateOption(a1)
  1597.     beq    .SkipNorthgate
  1598.     lea    NorthgateTable(pc),a2
  1599.     move.w    ie_Code(a0),d0
  1600.     bclr    #7,d0
  1601. .NorthgateLoop:
  1602.     move.b    (a2),d1
  1603.     beq    .EndNorthgate
  1604.     addq.l    #3,a2
  1605.     cmp.b    d0,d1
  1606.     bne    .NorthgateLoop
  1607.     and.w    #$80,ie_Code(a0)
  1608.     move.b    -2(a2),d0
  1609.     or.b    d0,ie_Code+1(a0)
  1610.     move.b    -1(a2),d0
  1611.     bmi    .EndNorthgate
  1612.     bset    d0,ie_Qualifier+1(a0)
  1613. .EndNorthgate:
  1614. .SkipNorthgate:
  1615.  
  1616.     btst    #IEQUALIFIERB_LCOMMAND,ie_Qualifier+1(a0)
  1617.     bne    .DoLAmiga
  1618.  
  1619. ;Blank mouse pointer
  1620.     tst.l    MBlankOption(a1)
  1621.     beq    .NoMBlank
  1622.     lea    BlankMouse(pc),a2
  1623.     bsr    DoFunc
  1624. .NoMBlank:
  1625.     bra    .Next
  1626.  
  1627. .DoLAmiga:
  1628.     tst.l    CmdOption(a1)
  1629.     beq    .Next
  1630.     cmp.w    #$45,ie_Code(a0)    ;ESC?
  1631.     bne    .Next
  1632.     clr.b    ie_Class(a0)
  1633.     lea    PopCLI(pc),a2
  1634.     bsr    DoFunc
  1635.     bra    .End
  1636.  
  1637. .NotKey:    bsr    RestoreScreen
  1638. .Timer:    move.w    ib_MouseX(a6),d0
  1639.     move.w    ib_MouseY(a6),d1
  1640.     cmp.b    #IECLASS_RAWMOUSE,ie_Class(a0)
  1641.     beq    .DoMouse
  1642.     cmp.w    CurrentX(a1),d0
  1643.     bne    .DoMouse
  1644.     cmp.w    CurrentY(a1),d1
  1645.     beq    .Next
  1646.  
  1647. .DoMouse:
  1648.     move.w    d0,CurrentX(a1)
  1649.     move.w    d1,CurrentY(a1)
  1650.     tst.l    MBlankOption(a1)
  1651.     beq    .NoRestore
  1652.     move.l    ie_TimeStamp(a0),MouseTime(a1)
  1653.     lea    RestoreMouse(pc),a2
  1654.     bsr    DoFunc
  1655. .NoRestore:
  1656.  
  1657. ;Perform SunMouse
  1658.     tst.l    SunMouseOption(a1)
  1659.     beq    .SkipSunMouse
  1660.     move.w    ie_Qualifier(a0),d0
  1661.     and.w    #IEQUALIFIER_LEFTBUTTON+IEQUALIFIER_RBUTTON+IEQUALIFIER_MIDBUTTON,d0
  1662.     bne    .SkipSunMouse
  1663.     cmp.w    #IECODE_LBUTTON+IECODE_UP_PREFIX,ie_Code(a0)
  1664.     beq    .SkipSunMouse
  1665.     move.l    SunMouseDelayOption(a1),a2
  1666.     move.l    a2,d0
  1667.     beq    .SkipLoad
  1668.     move.l    (a2),d0
  1669. .SkipLoad:
  1670.     addq.l    #1,d0
  1671.     move.l    d0,SunMouseDelay(a1)
  1672. .SkipSunMouse:
  1673.  
  1674. ;Perform click-to-back.
  1675.     cmp.w    #IECODE_RBUTTON,ie_Code(a0)
  1676.     bne    .NoCTB
  1677.     move.w    ie_Qualifier(a0),d0
  1678.     btst    #IEQUALIFIERB_LEFTBUTTON,d0
  1679.     beq    .DoSunRMB
  1680.     tst.l    STBOption(a1)
  1681.     bne    .DoCTB
  1682.     tst.l    CTBOption(a1)
  1683.     beq    .NoCTB
  1684. .DoCTB:    lea    CTB(pc),a2
  1685.     bsr    DoFunc
  1686.     clr.b    ie_Class(a0)
  1687.     bra    .Next
  1688.  
  1689. .DoSunRMB:
  1690.  
  1691. ;Perform SunRMB
  1692.     tst.l    SunRMBOption(a1)
  1693.     beq    .SkipSunRMB
  1694.     lea    ActivateWindow(pc),a2
  1695.     bsr    DoFunc
  1696. .SkipSunRMB:
  1697.  
  1698. .NoCTB:
  1699.  
  1700. ;Perform click-to-front.
  1701.     tst.l    CTFOption(a1)
  1702.     beq    .NoCTF
  1703.     cmp.w    #IECODE_LBUTTON,ie_Code(a0)
  1704.     bne    .NoCTF
  1705.     btst    #IEQUALIFIERB_LCOMMAND,ie_Qualifier+1(a0)
  1706.     bne    .NoCTF    ;to avoid interferring with Snap
  1707.     lea    CTF(pc),a2
  1708.     bsr    DoFunc
  1709. .NoCTF:
  1710.  
  1711. ;Perform acceleration.
  1712.     tst.l    AccelOption(a1)
  1713.     beq    .Next
  1714.  
  1715.     move.l    ThreshOption(a1),d0
  1716.     beq    .T1
  1717.     move.l    d0,a2
  1718.     move.l    (a2),d0
  1719. .T1:    move.w    ie_X(a0),d1
  1720.     bpl    .PosX
  1721.     neg.w    d1
  1722. .PosX:    cmp.w    d0,d1
  1723.     bls    .SkipX    ;below threshold
  1724.     move.l    AccelOption(a1),a2
  1725.     move.l    (a2),d1
  1726.     muls.w    ie_X(a0),d1
  1727.     tst.w    ie_X(a0)
  1728.     bpl    .SubDampX
  1729.     add.w    DampingConstant(a1),d1
  1730.     bra    .DampX
  1731. .SubDampX:
  1732.     sub.w    DampingConstant(a1),d1
  1733. .DampX:    move.w    d1,ie_X(a0)
  1734. .SkipX:    move.w    ie_Y(a0),d1
  1735.     bpl    .PosY
  1736.     neg.w    d1
  1737. .PosY:    cmp.w    d0,d1
  1738.     bls    .EndAccel
  1739.     move.l    AccelOption(a1),a2
  1740.     move.l    (a2),d1
  1741.     muls.w    ie_Y(a0),d1
  1742.     tst.w    ie_Y(a0)
  1743.     bpl    .SubDampY
  1744.     add.w    DampingConstant(a1),d1
  1745.     bra    .DampY
  1746. .SubDampY:
  1747.     sub.w    DampingConstant(a1),d1
  1748.  
  1749. .DampY:    move.w    d1,ie_Y(a0)
  1750. .EndAccel:
  1751.  
  1752. .Next:    move.l    a0,d1
  1753.     move.l    (a0),d0
  1754.     move.l    d0,a0
  1755.     bne    .Loop
  1756.  
  1757. ;Check for time-outs (mouse and screen blanking)
  1758.     move.l    d1,a0
  1759.     tst.l    MBlankOption(a1)
  1760.     beq    .NoMTime
  1761.     tst.l    MBlankWindow(a1)
  1762.     bne    .NoMTime
  1763.     move.l    MBlankOption(a1),a0
  1764.     move.l    (a0),d0    ;get value in seconds
  1765.     move.l    d1,a0
  1766.     move.l    ie_TimeStamp(a0),d1
  1767.     tst.l    MouseTime(a1)
  1768.     beq    .InitMBlank
  1769.     sub.l    MouseTime(a1),d1
  1770.     cmp.l    d0,d1    ;TimePassed ? UserSetting
  1771.     blo    .NoMTime
  1772.     lea    BlankMouse(pc),a2
  1773.     bsr    DoFunc
  1774. .NoMTime:
  1775.     tst.l    SBlankOption(a1)
  1776.     beq    .End
  1777.     btst    #STB_SBlanked,Status(a1)
  1778.     bne    .End
  1779.     push    a0
  1780.     move.l    SBlankOption(a1),a0
  1781.     move.l    (a0),d0    ;get value in seconds
  1782.     pop    a0
  1783.     move.l    ie_TimeStamp(a0),d1
  1784.     tst.l    ScreenTime(a1)
  1785.     beq    .InitSBlank
  1786.     sub.l    ScreenTime(a1),d1
  1787.     cmp.l    d0,d1    ;TimePassed ? UserSetting
  1788.     blo    .End
  1789.     bsr    BlankScreen
  1790.  
  1791. .End:    bsr    FreeIBase
  1792.     move.l    (sp)+,d0
  1793.     movem.l    (sp)+,d2/a2/a6
  1794.     rts
  1795. .InitMBlank:
  1796.     move.l    ie_TimeStamp(a0),MouseTime(a1)
  1797.     bra    .NoMTime
  1798. .InitSBlank:
  1799.     move.l    ie_TimeStamp(a0),ScreenTime(a1)
  1800.     bra    .End
  1801.  
  1802. ;Enter with global pointer in A1.
  1803. ;d0, d1, a0, a1, a5, and a6 are scratch.
  1804. ;Must always end with a "moveq #0,d0" to set the Z flag.
  1805.  
  1806. VBlankRoutine:
  1807.     tst.l    SunMouseDelay(a1)
  1808.     beq    .End
  1809.     subq.l    #1,SunMouseDelay(a1)
  1810.     bne    .End
  1811.     move.l    a2,-(sp)
  1812.     lea    ActivateWindow(pc),a2
  1813.     bsr    DoFunc
  1814.     move.l    (sp)+,a2
  1815. .End:    moveq    #0,d0
  1816.     rts
  1817.  
  1818. GlobalPtr:
  1819.     dc.l    0
  1820.  
  1821. NorthgateTable:
  1822. ;Assign PageUp/PageDown/Home/End to shift-cursor sequences
  1823.     dc.b    $6b,$4f,IEQUALIFIERB_LSHIFT
  1824.     dc.b    $6c,$4e,IEQUALIFIERB_LSHIFT
  1825.     dc.b    $6d,$4c,IEQUALIFIERB_LSHIFT
  1826.     dc.b    $6e,$4d,IEQUALIFIERB_LSHIFT
  1827.  
  1828. ;Change a couple keypad key assignments to be more Amiga-like.
  1829.     dc.b    $5c,$5b,0    ;'/' key -> ')' key
  1830.     dc.b    $5d,$5c,0    ;'*' key -> '/' key
  1831.     dc.b    $4a,$5d,0    ;'-' key -> '*' key
  1832.     dc.b    0
  1833.  
  1834. ProcName:    dc.b    'QMouse process',0
  1835. InputName:
  1836.     dc.b    'input.device',0
  1837. TrackName:
  1838.     dc.b    'trackdisk.device',0
  1839.     even
  1840.  
  1841. ;*************************** Debugging stuff *************************
  1842.  
  1843.     IFNE    INFO_LEVEL
  1844. KPutFmt:    movem.l    a2/a6,-(sp)
  1845.     move.l    4,a6
  1846.     lea    KPutChar(pc),a2
  1847.     SYS    RawDoFmt
  1848.     movem.l    (sp)+,a2/a6
  1849.     rts
  1850.  
  1851. KPutChar:
  1852.  
  1853. ;Serial
  1854.     comment |
  1855.     move.l    a6,-(sp)
  1856.     move.l    4,a6
  1857.     SYS    RawPutChar
  1858.     move.l    (sp)+,a6
  1859.     rts
  1860. |
  1861.  
  1862. ;Printer
  1863.     comment |
  1864.     move.b    #$ff,$bfe301
  1865. .Print:    btst    #0,$bfd000
  1866.     bne    .Print
  1867.     move.b    d0,$bfe101
  1868.     rts
  1869. |
  1870.  
  1871. ;Memory
  1872.     movem.l    a0-a1,-(sp)
  1873.     lea    MemPtr(pc),a1
  1874.     move.l    (a1),a0
  1875.     move.b    d0,(a0)+
  1876.     move.l    a0,(a1)
  1877.     movem.l    (sp)+,a0-a1
  1878.     rts
  1879. MemPtr:    dc.l    $300000
  1880.     ENDC
  1881.  
  1882. EndAllocCode:    ;end of code copied into allocated memory
  1883. ;***********************************************************************
  1884.  
  1885. NewProcTags:
  1886.     dc.l    NP_Entry
  1887. EntryPoint:
  1888.     dc.l    0
  1889.     dc.l    NP_Name
  1890. ProcNamePtr:
  1891.     dc.l    0
  1892.     dc.l    NP_Cli,-1
  1893.     dc.l    NP_Priority,TaskPriority
  1894.     dc.l    0    ;end of tags
  1895.  
  1896. Template:    dc.b    'M=MBLANK/K/N,'
  1897.     dc.b    'S=SBLANK/K/N,'
  1898.     dc.b    'N=NOFLICKER/S,'
  1899.     dc.b    'CMD/K,'
  1900.     dc.b    'A=ACCELERATION/K/N,'
  1901.     dc.b    'T=THRESHOLD/K/N,'
  1902.     dc.b    'CTB=CLICKTOBACK/S,'
  1903.     dc.b    'STB=SCREENTOBACK/S,'
  1904.     dc.b    'CTF=CLICKTOFRONT/K/N,'
  1905.     dc.b    'SUNMOUSE/S,'
  1906.     dc.b    'SUNKEY/S,'
  1907.     dc.b    'NORTHGATE/S,'
  1908.     dc.b    'NOBEEP/S,'
  1909.     dc.b    'NOCLICK/K/N,'
  1910.     dc.b    'VERIFY/S,'
  1911.     dc.b    'NOVERIFY/S,'
  1912.     dc.b    'STAR/S,'
  1913.     dc.b    'NoWBenchToFront/S,'
  1914.     dc.b    'PUBCHANGE/S,'
  1915.     dc.b    'SunMouseDelay/K/N,'
  1916.     dc.b    'ImmBlank/S,'
  1917.     dc.b    'NoActivate/S,'
  1918.     dc.b    'SunRMB/S,'
  1919.     dc.b    'QUIT/S',0
  1920.  
  1921. IntName:    dc.b    'intuition.library',0
  1922. GraphName:
  1923.     dc.b    'graphics.library',0
  1924. DosName:    dc.b    'dos.library',0
  1925. LayersName:
  1926.     dc.b    'layers.library',0
  1927. UtilityName:
  1928.     dc.b    'utility.library',0
  1929. BadArgs:    dc.b    'Bad arguments.',$a,0
  1930.  
  1931.     dc.b    '$VER: QMouse 2.90 (4.1.94)',$a,0
  1932.  
  1933. ;The ordering here is special: data registers first, then address
  1934. ;registers, so that MOVEM may be used to save/restore the data.
  1935.  
  1936.     STRUCTURE    pt,0
  1937.     LONG    pt_Height
  1938.     LONG    pt_Width
  1939.     LONG    pt_XOffset
  1940.     LONG    pt_YOffset
  1941.     LONG    pt_Window
  1942.     LONG    pt_Pointer
  1943.     BYTE    TagVersion    ;special boolean indicator
  1944.     BYTE    pt_pad
  1945.     LABEL    pt_Sizeof
  1946.  
  1947. ResidentCodeSize    equ    EndAllocCode-StartAllocCode
  1948.  
  1949.     STRUCTURE    Data,0
  1950.     WORD    Nothing    ;to make zero special
  1951.  
  1952.     LABEL    Sigs
  1953.     LONG    QuitSig
  1954.     LONG    FuncSig
  1955.     LABEL    EndSigs
  1956.  
  1957.     LABEL    Semaphores
  1958.     STRUCT    MySemaphore,SS_SIZE
  1959.     STRUCT    CloseWindowSemaphore,SS_SIZE
  1960.     STRUCT    CloseScreenSemaphore,SS_SIZE
  1961.     STRUCT    CloseWBSemaphore,SS_SIZE
  1962.     LABEL    EndSemaphores
  1963.  
  1964.     LONG    Task
  1965.     LONG    InputMsgPort
  1966.     LONG    InputIORequest
  1967.     STRUCT    InputInterrupt,IS_SIZE
  1968.     LONG    IntBase
  1969.     LONG    GraphBase
  1970.     LONG    LayersBase
  1971.     LONG    _UtilityBase
  1972.     STRUCT    ScreenList,SCREENLISTSIZE*8
  1973.     STRUCT    PointerList,POINTERLISTSIZE*pt_Sizeof
  1974.     STRUCT    TaskQueue,MAXQUEUE*4+4
  1975.     LONG    OldCloseScreen
  1976.     LONG    OldCloseWorkBench
  1977.     LONG    OldCloseWindow
  1978.     LONG    OldSetPointer
  1979.     LONG    OldSetWindowPointerA
  1980.     LONG    OldClearPointer
  1981.     LONG    OldDisplayBeep
  1982.     LONG    OldOpenWindowTagList
  1983.     LONG    DosBase
  1984.     LONG    ArgPtr
  1985.     STRUCT    ResidentCode,ResidentCodeSize
  1986.     LONG    MouseTime    ;timeout for mouse blanking
  1987.     LONG    ScreenTime    ;for screen blanking
  1988.     LONG    BlankScreenPtr
  1989.     LONG    BlankScreenWindowPtr
  1990.     LONG    MBlankWindow
  1991.     WORD    DampingConstant
  1992.     LONG    ClickWindow
  1993.     STRUCT    ClickTime,TV_SIZE
  1994.     LONG    ClickCount
  1995.     LONG    Path
  1996.     LONG    ChipData
  1997.     LONG    RealBackground
  1998.     LONG    OriginalCopInit
  1999.     WORD    CurrentX
  2000.     WORD    CurrentY
  2001.     LONG    WaitLineAddress
  2002.     LONG    CurrentTopScreen
  2003.     LONG    CurrentActiveScreen
  2004.     LONG    CurrentActiveWindow
  2005.     LONG    SunMouseDelay
  2006.     STRUCT    VBlankServer,IS_SIZE
  2007.     LONG    IBaseLock
  2008.  
  2009.     LABEL    Options
  2010.     LONG    MBlankOption
  2011.     LONG    SBlankOption
  2012.     LONG    FlickerOption
  2013.     LONG    CmdOption
  2014.     LONG    AccelOption
  2015.     LONG    ThreshOption
  2016.     LONG    CTBOption
  2017.     LONG    STBOption
  2018.     LONG    CTFOption
  2019.     LONG    SunMouseOption
  2020.     LONG    SunKeyOption
  2021.     LONG    NorthGateOption
  2022.     LONG    BeepOption
  2023.     LONG    NoClickOption
  2024.     LONG    VerifyOption
  2025.     LONG    NoVerifyOption
  2026.     LONG    StarOption
  2027.     LONG    NoWBenchToFrontOption
  2028.     LONG    PubChangeOption
  2029.     LONG    SunMouseDelayOption
  2030.     LONG    ImmBlankOption
  2031.     LONG    NoActivateOption
  2032.     LONG    SunRMBOption
  2033.     LONG    QuitOption
  2034.  
  2035.     BYTE    HandlerInstalled
  2036.     BYTE    Status    ;various status bits (defined below)
  2037.     LABEL    Data_Sizeof
  2038.  
  2039. ;Bit definitions for Status
  2040.     BITDEF    ST,SBlanked,0
  2041.     BITDEF    ST,IntInstalled,1
  2042.  
  2043. NumSigs    equ    (EndSigs-Sigs)/4
  2044. NumSemaphores    equ    (EndSemaphores-Semaphores)/SS_SIZE
  2045.  
  2046.     STRUCTURE    CData,0
  2047.     STRUCT    ZeroMouse,12
  2048.     STRUCT    Copper,MaxCopperSize+4*4
  2049.     LABEL    CData_Sizeof
  2050.  
  2051.     end
  2052.