home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
HomeWare 14
/
HOMEWARE14.bin
/
utils2
/
mymous12.arj
/
MYMOUSE.ASM
< prev
next >
Wrap
Assembly Source File
|
1994-02-12
|
26KB
|
946 lines
;$VER: MyMouse.asm 1.2 (12.02.93)
;Written by Andrew Forrest
;Based on QMouse by Dan Babcock
;Assembled with Devpac 3
nolist
; How it works:
; The program spawns a child process which remains resident in memory and
; does the funky stuff. If the resident process already exists, the program
; alters the child's parameters and sends it an update signal. The main
; program allocates stuff that's _always_ needed, the child allocates other
; stuff on the fly (input.device, for example).
; While it is setting up, the child makes itself invisible by changing its
; name. This ensures that a seach for the child (by name) will always find
; the child prepared.
; PROCESS IS GUARUNTEED TO STAY PUT (cos you can't totally unpatch functions)
include everything.i
include hardware/dmabits.i
Execbase equ 4
_custom equ $dff000
;*╗╗ Semaphore macros
; Use carefully!
; Take a5=GlobalPtr; a6=ExecBase
; Scratch a0
CriticalSection macro
lea MySemaphore(a5),a0
just ObtainSemaphore
endm
EndCritical macro
lea MySemaphore(a5),a0
just ReleaseSemaphore
endm
BlankScreen macro
move.w #DMAF_COPPER+DMAF_RASTER,dmacon+_custom.l
clr.w color+_custom.l
endm
UnBkScreen macro
move.w #DMAF_SETCLR+DMAF_COPPER+DMAF_RASTER,dmacon+_custom.l
endm
;*╗╗ Code entrypoint
move.l Execbase,a6
cmp.w #37,LIB_VERSION(a6)
bhs GoodVersion
;Oh no, we're running under 1.3 or something
lea DosName(pc),a1
moveq.l #0,d0
just OpenLibrary
tst.l d0
beq.s ErrorEnd
move.l d0,a6
just Output
move.l d0,d1
moveq #SorryLength,d3
lea Sorry(pc),a0
move.l a0,d2
just Write
move.l a6,a1
move.l Execbase,a6
just CloseLibrary
ErrorEnd: moveq #RETURN_FAIL,d0
rts
dc.b '$VER: MyMouse 1.2 (08.02.94)',LF,0
Sorry dc.b 'You need (at least) Kickstart 2.0 to run this program.',LF,0
SorryLength equ *-Sorry
even
GoodVersion:
***************************************************************************
* Start of Main program
***************************************************************************
; Registers:
; A5=^Global data structure
; D7=^Installed process, _if it exists yet_, else NULL
lea ProcName(pc),a1
just FindTask
move.l d0,d7
bne.s .else ; If process doesn't exist then
bsr Allocate ; Reserve some space for it
bne Deallocate
bsr.s Read_Args ; (returns Z flag success)
bne Deallocate
bsr Install ; (returns pointer to new task)
beq Deallocate
bra.s .end_ok ; else
.else move.l d7,a1
move.l TC_Userdata(a1),a5 ; Get global structure
bsr.s Read_Args
bne.s .end_fail ;(If couldn't read args, fail)
move.l d7,a1
move.l UpdateSig(a5),d0
just Signal ; Send task a signal to wake it up
.end_ok moveq #RETURN_OK,d0
.end_fail rts
***************************************************************************
Read_Args: ;*╗╗ Replace arguments in global structure with new ones
; Takes a5=GlobalPtr; Returns OK or FAIL code; a6=Execbase
; Scratches d0-d4/a0-a1/a4
CriticalSection
lea Template(pc),a0
move.l a0,d1
lea Options(a5),a0
move.l a0,d2
moveq #NumOptions-1,d0
.clear_loop clr.l (a0)+
dbra d0,.clear_loop
moveq #0,d3 ;no custom rdarg structure
move.l DosBase(a5),a6
just ReadArgs
tst.l d0
beq.s .fail
move.l ArgPtr(a5),d1 ; get _old_ arguments
beq.s .use
push.l d0
just FreeArgs ; and free them if necessary
pop.l d0
.use move.l d0,ArgPtr(a5) ; then install _new_ arguments
move.l Execbase,a6
moveq.l #RETURN_OK,d0
.end EndCritical
tst.l d0 ; (return D0 and CCR)
rts
.fail move.l Execbase,a6
moveq.l #RETURN_FAIL,d0
bra.s .end
***************************************************************************
Install:
; Takes a5=GlobalPtr; a6=Execbase; Returns d0=^NewTask or NULL
; Scratches a0-a1/d0-d1
;*╗╗ Copy resident part of code into allocated memory
lea StartResidentCode(pc),a0 ;source
lea ResidentCode(a5),a1 ;destination
move.l #ResidentCodeLength,d0 ;size
just CopyMem
just CacheClearU ;for 020/030/040
;*╗╗ Initialize static data
move.b #HANDLERPRI,InputInterrupt+LN_PRI(a5)
move.l a5,InputInterrupt+IS_DATA(a5)
lea IntRoutine-StartResidentCode+ResidentCode(a5),a0
move.l a0,InputInterrupt+IS_CODE(a5)
move.l a5,GlobalPtr-StartResidentCode+ResidentCode(a5)
;*╗╗ Get stack for command.
move.l DosBase(a5),a6
just Cli
move.l d0,a0
move.l cli_DefaultStack(a0),d0
lsl.l #2,d0
move.l d0,CmdStackSize-StartResidentCode+ResidentCode(a5)
;*╗╗ Start the baby process
lea NewProcTags-StartResidentCode+ResidentCode(a5),a0
lea NEW_LIFE-StartResidentCode+ResidentCode(a5),a1
move.l a1,EntryPointTag(a0)
lea ProcName-StartResidentCode+ResidentCode(a5),a1
not.b (a1) ; (So task is initially invisible)
move.l a1,ProcNameTag(a0)
move.l a0,d1 ; Get tag list into d1
just CreateNewProc
tst.l d0
move.l Execbase,a6
rts
***************************************************************************
Allocate:
; Takes a6=Execbase; Returns OK or FAIL; a5=GlobalPtr or NULL
; Scratches a0-a3/d0-d1
;*╗╗ Allocate global data structure
move.l #Data_SIZEOF,d0
move.l #MEMF_CLEAR|MEMF_PUBLIC,d1 ;(Got to be PUBLIC)
just AllocMem
move.l d0,a5 ; Need to store in a5 _before_ testing
tst.l d0
beq.s .cant_alloc
;*╗╗ Allocate Chip RAM data
move.l #MouseData_SIZEOF,d0
move.l #MEMF_CLEAR|MEMF_PUBLIC|MEMF_CHIP,d1
just AllocMem
move.l d0,MouseChipData(a5)
beq.s .cant_alloc
;*╗╗ Open libraries
lea LibTable(pc),a2
lea FirstLibBase(a5),a3
moveq #NumLibs-1,d2
.loop move.w (a2)+,d0 ; library version to open
ext.l d0 ; version should be longword
move.w (a2)+,a1
lea LibTable(pc,a1.w),a1 ; name of library
just OpenLibrary
move.l d0,(a3)+
beq.s .cant_alloc
dbra d2,.loop
;*╗╗ Set up semaphore
lea MySemaphore(a5),a0
just InitSemaphore
moveq #RETURN_OK,d0 ; Set d0 and CCR
rts
.cant_alloc moveq #RETURN_FAIL,d0
rts
***************************************************************************
LibTable: dc.w 37,DosName-LibTable
dc.w 33,IntName-LibTable
dc.w 33,LayName-LibTable
NumLibs: equ (*-LibTable)/4
***************************************************************************
***************************************************************************
StartResidentCode: ;The following code is copied into allocated memory.
***************************************************************************
; Everything except Deallocate is called only from child process
***************************************************************************
Deallocate: ;*╗╗ Close libraries (called either from parent or child)
; Takes a5=GlobalPtr; a6=Execbase; No return value.
; Scratches a0-a2/d0-d2
move.l a5,d0 ; Does global structure exist?
beq.s .noData
lea FirstLibBase(a5),a2
moveq #NumLibs-1,d2
.loop move.l (a2)+,d0
beq.s .endif
move.l d0,a1
just CloseLibrary
.endif dbra d2,.loop
;*╗╗ Free chip data.
move.l MouseChipData(a5),d0
beq.s .noChipData
move.l d0,a1
move.l #MouseData_SIZEOF,d0
just FreeMem
.noChipData
;*╗╗ Free global structure
lea (a5),a1
move.l #Data_SIZEOF,d0
jmp _LVOFreeMem(a6) ; Jump in case we are
.noData ; deallocating _this_ code
rts
***************************************************************************
; Here lies the start of the child process' program
; Except where noted, subroutines should preserve a5-a6 (and the stack
; pointer of course), but may trash other registers
NEW_LIFE: move.l Execbase,a6
move.l GlobalPtr(pc),a5
bsr InitialiseResident ; Get signals
bne.s Deallocate ; (_not_ a branch to subrtn)
BIG_LOOP: bsr EvaluateOptions
bne.s KillHandler
bsr AllocateResident ; Get so far ungot resources
wait_loop: move.l AllSignals(a5),d0
just Wait ; \ Routines called from this section
move.l d0,d7 ; / may trash any register except a5 or d7
and.l CLISig(a5),d0
beq.s .noCLI
* move.l Execbase,a6 (already the case)
bsr CLI ; Expects a6=Execbase (nobody's perfect:-)
.noCLI move.l d7,d0
and.l MouseBlankSig(a5),d0
beq.s .noMB
bsr MouseBlankUpdate
.noMB tst.l ActivateScreenOption(a5)
beq.s .noActiWind ; If window-activation is off anyway then
move.l d7,d0 ; ...don't bother to check for the signals
and.l CloseScreenSig(a5),d0
beq.s .noClose
bsr Closure
.noClose move.l d7,d0
and.l ScreenDepthSig(a5),d0
beq.s .noDepth
bsr.s Depth
.noDepth
.noActiWind move.l Execbase,a6
and.l UpdateSig(a5),d7
beq.s wait_loop
bra.s BIG_LOOP
KillHandler:
bclr #STB_HandlerInstalled,Status(a5)
beq.s .end
move.l InputIORequest(a5),a1
move.w #IND_REMHANDLER,IO_COMMAND(a1)
lea InputInterrupt(a5),a0
move.l a0,IO_DATA(a1)
just DoIO
bclr #STB_DoMBlank,Status(a5)
bsr MouseBlankUpdate ; Switch off mouse-blanking
bclr #STB_SBlanked,Status(a5)
UnBkScreen ; Switch off screen-blanking
.end bra.s wait_loop
;****************************************************************************
; This routine is called asynchronously whenever Intuition's ScreenDepth
; routine gets called (i.e. any time a screen is rearranged).
Depth: move.l IntBase(a5),a6
moveq #0,d0
just LockIBase ; Start critical section
move.l d0,d2
move.l ib_ActiveScreen(a6),a0 ; \ Remember to keep track
move.l ib_ActiveWindow(a6),a1 ; | of _previous_ screen-
bsr AssociateWindow ; / window combination
move.l ib_FirstScreen(a6),a0 ; \ Look up `active' window
bsr IndexScreenTable ; / of newly frontmost screen
tst.l d0
beq.s .fail ; If we can find a window for screen,
move.l d0,a0 ; ...then activate that window
just ActivateWindow ; (Defered so should be OK inside lock)
.fail move.l d2,a0
just UnlockIBase ; End critical section
rts
; This one gets called on screen closure.
Closure: move.l IntBase(a5),a6
moveq #0,d0
just LockIBase ; Start critical section
move.l d0,a0
bsr PruneScreenTable ; (Alters no registers)
just UnlockIBase ; End critical section
or.l ScreenDepthSig(a5),d7 ; (Must change window too)
rts
; Executes a CLI command (like NewShell, for example)
; *** Expects a6=Execbase
CLI: CriticalSection ; Critical so CMD parameter can't change
move.l CmdOption(a5),d1 ;Pop CLI
beq.s .fail
pushm.l d1/a6
move.l IntBase(a5),a6 ;Workbench To Front
just WBenchToFront
popm.l d1/a6
move.l DosBase(a5),a6
lea Tags(pc),a1
bsr.s OpenNil
move.l d0,InputTag(a1)
beq.s .end
bsr.s OpenNil
move.l d0,OutputTag(a1)
beq.s .closeinput
move.l a1,d2 ;tags
just SystemTagList
tst.l d0
beq.s .end ; If sucessful, should deallocate itself
move.l OutputTag+Tags(pc),d1
just Close
.closeinput move.l InputTag+Tags(pc),d1
just Close
.end move.l Execbase,a6
.fail EndCritical
rts
Tags:
dc.l SYS_UserShell,0
dc.l SYS_Asynch,0
dc.l SYS_Input,0
InputTag equ *-4-Tags
dc.l SYS_Output,0
OutputTag equ *-4-Tags
dc.l NP_Priority,ShellPriority
dc.l NP_StackSize
CmdStackSize:
dc.l 0
dc.l 0 ;end of tag list
OpenNil: pushm.l a0-a1/d1-d2
lea NilName(pc),a0
move.l a0,d1
move.l #MODE_READWRITE,d2
just Open
popm.l a0-a1/d1-d2
rts
;****************************************************************************
InitialiseResident:
; Takes a5=GlobalPtr; a6=Execbase; Returns OK or FAIL
; Scratches d0-d2/a0-a1
suba.l a1,a1
just FindTask ; _Find_ yourself.
move.l d0,a0
move.l a5,TC_Userdata(a0)
move.l d0,Task(a5)
bsr InitialiseScreenTable ; Just set it up
;*╗╗ Allocate signals
moveq #NumSigs-1,d2
lea Sigs(a5),a2
.sigloop moveq #-1,d0
just AllocSignal
tst.l d0
bmi.s .fail
.ok moveq #0,d1
bset d0,d1
move.l d1,(a2)+
or.l d1,AllSignals(a5)
dbra d2,.sigloop
just Forbid
lea ProcName(pc),a1
move.b #InitialLetter,(a1)
just FindTask ; Search for process with same name
tst.l d0
bne.s .found_twin ; Oh, no -- duplicate name
move.l Task(a5),a1
move.l LN_NAME(a1),a1
move.b #InitialLetter,(a1) ; make process visible
just Permit
;*╗╗ Patch three Intuition routines. (Do this last)
;*╗╗ (all but first patch must be on V39 library)
lea PatchTable(pc),a2
lea OldRoutines(a5),a3
move.l IntBase(a5),a1 ; Library to patch
.patchloop move.w (a2)+,d1 ; LVO offset
beq.s .endpatch ; (exit if hit null-terminator)
move.w (a2)+,d0 ; Offset to new routine
tst.l (a3) ; If it is already patched
bne.s .nextpatch ; skip to the next one
lea PatchTable(pc,d0.w),a0 ; Get address of new routine
move.l a0,d0 ; d0 <- address of new routine
move.w d1,a0 ; a0 <- LVO offset
just SetFunction
move.l d0,(a3)+ ; Store ^old routine for posterity
.nextpatch move.l IntBase(a5),a1 ;\ Get ^Intuition for next
cmp.w #39,LIB_VERSION(a1) ;/ iteration and check version
bhs.s .patchloop ; Patch V39 Intuition only
.endpatch
moveq #RETURN_OK,d0
rts
.found_twin
.fail moveq #31,d2
.loop btst d2,AllSignals(a5)
beq.s .next
move.l d2,d0
just FreeSignal
.next dbra d2,.loop
moveq #RETURN_FAIL,d0
rts
PatchTable: dc.w _LVODisplayBeep,NewDisplayBeep-PatchTable
dc.w _LVOCloseScreen,NewCloseScreen-PatchTable
dc.w _LVOScreenDepth,NewScreenDepth-PatchTable
dc.w 0 ; NULL-terminate list
***************************************************************************
NewDisplayBeep:
move.l GlobalPtr(pc),a1
tst.l NoBeepOption(a1)
bne.s .endif
move.l OldDisplayBeep(a1),-(sp)
.endif rts
NewCloseScreen:
pushm.l a2/a5-a6
move.l GlobalPtr(pc),a5
move.l OldCloseScreen(a5),a2
jsr (a2)
move.l d0,a2 ; (Preserve return value)
move.l CloseScreenSig(a5),d0
bra.s sig
NewScreenDepth:
pushm.l a2/a5-a6
move.l GlobalPtr(pc),a5
move.l OldScreenDepth(a5),a2
jsr (a2)
move.l ScreenDepthSig(a5),d0
sig move.l Task(a5),a1
move.l Execbase,a6
just Signal
move.l a2,d0 ; (Restore return value)
popm.l a2/a5-a6
rts
***************************************************************************
; Here is the routine for allocating the baby task's resources
; If they cannot be allocated at first, the program tries again every time
; an update signal is recieved.
AllocateResident:
; Takes a5=GlobalPtr; a6=Execbase
; Scratches a0-a3/d0-d1
;*╗╗ Create an IORequest structure
move.l InputMsgPort(a5),d0
bne.s .endCreatePort ; Skip if port already there
just CreateMsgPort
move.l d0,InputMsgPort(a5)
beq.s .fail
.endCreatePort
move.l d0,a0
move.l InputIORequest(a5),d0 ; n.b. _not_ "tst.l Inpu..."
bne.s .endCreateReq ; Skip if req already there
moveq #IOSTD_SIZE,d0
just CreateIORequest
move.l d0,InputIORequest(a5)
beq.s .fail
.endCreateReq
;*╗╗ Open the input.device
btst #STB_InputDeviceOpened,Status(a5)
bne.s .endOpenInput
move.l d0,a1 ;IO request
lea InputName(pc),a0 ;device name
moveq #0,d0 ;unit number
moveq #0,d1 ;flags
just OpenDevice
tst.l d0
bne.s .fail
bset #STB_InputDeviceOpened,Status(a5)
.endOpenInput
;*╗╗ Install the input handler
bset #STB_HandlerInstalled,Status(a5)
bne.s .endInstallHandl
move.l InputIORequest(a5),a1
move.w #IND_ADDHANDLER,IO_COMMAND(a1)
lea InputInterrupt(a5),a0
move.l a0,IO_DATA(a1)
just DoIO
.endInstallHandl
.fail rts
***************************************************************************
EvaluateOptions:
; Takes a5=GlobalPtr; a6=Execbase; Scratches d0-d1/a0-a2
;*╗╗ Copy some parameters (for input-handler)
CriticalSection ; So no one changes them while we do it
lea CacheTable(pc),a1
lea OptionCaches(a5),a2
move.w #CacheNum-1,d1
.loop move.w (a1)+,d0
move.l (a5,d0.w),d0
.if beq.s .else
move.l d0,a0
move.l (a0),d0
bra.s .endif
.else moveq #-1,d0 ; Unselected options become -1
.endif move.l d0,(a2)+
dbra d1,.loop
.endloop EndCritical
;*╗╗ Ensure mouse/screen is never left blanked
tst.l MouseBlank(a5)
bge.s .mblnk_on ; Skip if mouse blanking was turned on
bclr #STB_DoMBlank,Status(a5)
bsr MouseBlankUpdate
.mblnk_on tst.l ScreenBlank(a5)
bgt.s .sblnk_on ; Skip if screen blanking was turned on
bclr #STB_SBlanked,Status(a5)
UnBkScreen
.sblnk_on
;*╗╗ Initialize damping constant.
move.l Acceleration(a5),d0
bmi.s .no_damp
move.l d0,a0
move.l (a0),d0
subq.l #1,d0
move.l Threshold(a5),d1
bpl.s .use_thresh
moveq #0,d1
.use_thresh addq.l #1,d1
mulu.w d0,d1
move.w d1,DampingConstant(a5)
.no_damp
.okay
*╗╗ Check that at least one command-line option was specified
lea Options(a5),a0
moveq #NumOptions-1,d0
.chk_loop tst.l (a0)+
bne.s .dontdie
dbra d0,.chk_loop
bsr ShutDownScreenTable ; If no options deallocate mem
moveq #RETURN_FAIL,d0 ; Return nonzero if no options
rts
.dontdie moveq #RETURN_OK,d0 ; Return zero if at least 1 selected
rts
CacheTable dc.w MBlankOption
dc.w SBlankOption
dc.w AccelOption
dc.w ThreshOption
dc.w CTFOption
dc.w ClickBorderOption
CacheNum equ (*-CacheTable)/2
;****************************************************************************
include MM-Handler.asm
include ScreenTable.asm
;****************************************************************************
;Utility routines
;*╗╗ Get window associated with current mouse position.
; Takes a5=GlobalPtr; a6=IntBase; Returns d0=Window; D1=Screen
; (assume we don't need to lock IntuitionBase)
GetWindow:
pushm.l d4/a0-a1/a4/a6
lea (a6),a4
move.l LayBase(a5),a6
move.l ib_FirstScreen(a4),d4
.loop tst.l d4
beq.s .err_end
move.l d4,a0
move.l sc_NextScreen(a0),d4
move.w sc_MouseX(a0),d0
bmi.s .loop
move.w sc_MouseY(a0),d1
bmi.s .loop
push.l a0
lea sc_LayerInfo(a0),a0
just WhichLayer
pop.l d1
tst.l d0
beq.s .end
move.l d0,a0
move.l lr_Window(a0),d0
.end popm.l d4/a0-a1/a4/a6
rts
.err_end: moveq #0,d0
moveq #0,d1
bra .end
DoWindowToFront:
; Takes d0=^Window or NULL (no effect); a5=GlobalPtr
; scratches nothing
tst.l d0
beq.s .abort
pushm.l d0-d1/a0-a1/a6
move.l IntBase(a5),a6
move.l d0,a0
move.l wd_WLayer(a0),d0
beq.s .end
move.l d0,a1
move.l lr_ClipRect(a1),d0
beq.s .end
move.l d0,a1
tst.l cr_Next(a1) ; Do nothing if it is not covered
beq.s .end
move.l wd_Flags(a0),d0
and.l #WFLG_BACKDROP,d0
bne.s .end ; or if it is a backdrop window
just WindowToFront
.end popm.l d0-d1/a0-a1/a6
.abort rts
; Blank or unblank the mouse, depending on Globals.Status.DoMBlank.
; Takes nil (but needs a5=^Globals); Trashes/Returns nil;
; NEVER call with Intbase locked
MouseBlankUpdate:
pushm.l a0-a1/a6/d0-d2
move.l IntBase(a5),a6
moveq #0,d0
just LockIBase ; *** Critical section
move.l d0,d2
move.l Execbase,a6
just Forbid ; (make sure no one changes mouse)
btst #STB_DoMBlank,Status(a5)
beq.s .restore
.blank bsr BlankMouse
bra.s .endif
.restore bsr RestoreMouse
.endif just Permit ; (allow other tasks)
move.l d2,a0
move.l IntBase(a5),a6
just UnlockIBase ; *** End critical section
popm.l a0-a1/a6/d0-d2
rts
;*╗╗ Blank the current window's mouse pointer
; Takes a5=GlobalPtr; IBase must be locked; Scratches nothing
BlankMouse: pushm.l a0-a1/a6/d0-d3
move.l IntBase(a5),a6
move.l ib_ActiveWindow(a6),a0
cmp.l MBlankWindow(a5),a0
beq.s .same_wind ; If a different window is now active then
.other_win bsr.s RestoreMouse ; unblank it first
bra.s .notblanked ; Else
.same_wind move.l wd_Pointer(a0),d0
cmp.l MouseChipData(a5),d0 ; If still blanked, give up
beq.s .end_blank
.notblanked move.l a0,MBlankWindow(a5) ; Remember window & its pointer
beq.s .no_blank ; Quit if no current window(!)
move.l wd_WScreen(a0),MBlankScreen(a5) ; Remember screen
clr.l OldPointer+Ptr_Image(a5) ; Assume no custom image
move.l wd_Pointer(a0),d0
cmp.l MouseChipData(a5),d0
beq.s .end_blank ; Quit if already blanked
move.l d0,OldPointer+Ptr_Image(a5)
move.l wd_PtrDimensions(a0),OldPointer+Ptr_Dimensions(a5)
move.l MouseChipData(a5),a1
moveq #1,d0 ;height
moveq #16,d1 ;width
moveq #0,d2 ;xoffset
moveq #0,d3 ;yoffset
just SetPointer
.end_blank bset #STB_MBlanked,Status(a5)
.no_blank popm.l a0-a1/a6/d0-d3
rts
;*╗╗ Restore old mouse image
; Takes a5=GlobalPtr; IBase must be locked; Scratches nil
RestoreMouse:
pushm.l a0-a1/a6/d0-d3
move.l IntBase(a5),a6
move.l MBlankWindow(a5),d0
bne.s .knownblnk ; If nothing is apparently blanked then
.unknwnblnk move.l ib_ActiveWindow(a6),d0 ; Try the active window
beq.s .end_RMouse ; (quit if no active window)
move.l d0,a0
clr.l OldPointer+Ptr_Image(a5) ;(whose image we don't know)
bra.s .foundwind
.knownblnk move.l MBlankScreen(a5),d2 ; We know it's on this screen
move.l ib_FirstScreen(a6),d1 ; Start with the first screen
.screenloop beq.s .end_RMouse ; While screen^ =/= NULL
move.l d1,a0 ; Get ^ into address reg
cmp.l d1,d2 ; Compare screen to target
beq.s .foundscrn ; Exit if found target screen
move.l sc_NextScreen(a0),d1 ; Get next screen
bra.s .screenloop ; End while
.foundscrn move.l sc_FirstWindow(a0),d1 ; Start with first window
.windowloop beq.s .end_RMouse ; While window^ =/= NULL
move.l d1,a0
cmp.l d0,d1 ; Compare window with target
beq.s .foundwind ; Exit if this is the window
move.l wd_NextWindow(a0),d1 ; Next window
bra.s .windowloop ; End while
.foundwind ; We now know window exists and that a0=^window
move.l wd_Pointer(a0),d0
cmp.l MouseChipData(a5),d0
bne.s .end_RMouse ; Skip if already unblanked
move.l OldPointer+Ptr_Image(a5),a1
move.l a1,d0
bne.s .restoreold ; If no image pointer then
just ClearPointer ; Restore default pointer
bra.s .end_RMouse ; Else
.restoreold move.b OldPointer+Ptr_Height(a5),d0
move.b OldPointer+Ptr_Width(a5),d1
move.b OldPointer+Ptr_XOffset(a5),d2
move.b OldPointer+Ptr_YOffset(a5),d3
ext.w d0
ext.w d1
ext.w d2
ext.w d3
just SetPointer ; Restore custom pointer
.end_RMouse bclr #STB_MBlanked,Status(a5)
popm.l a0-a1/a6/d0-d3
rts
***************************************************************************
GlobalPtr: ds.l 1
NorthgateTable:
;*╗╗ Assign PageUp/PageDown/Home/End to shift-cursor sequences
dc.b $6b,$4f,IEQUALIFIER_LSHIFT
dc.b $6c,$4e,IEQUALIFIER_LSHIFT
dc.b $6d,$4c,IEQUALIFIER_LSHIFT
dc.b $6e,$4d,IEQUALIFIER_LSHIFT
; ;*╗╗ Change a couple keypad key assignments to be more Amiga-like.
; dc.b $5c,$5b,0 ;'/' key -> ')' key
; dc.b $5d,$5c,0 ;'*' key -> '/' key
; dc.b $4a,$5d,0 ;'-' key -> '*' key
dc.b 0
ProcName: dc.b 'Funky baby Mouse process 1.2',0 ;╗╗ Name of child process
InitialLetter equ 'F' ;╗╗ child's first initial
InputName: dc.b 'input.device',0
NilName: dc.b 'NIL:',0
even
NewProcTags: ; In allocated memory so command can be pure
dc.l NP_Entry
EntryPointTag equ *-NewProcTags
dc.l 0
dc.l NP_Name
ProcNameTag equ *-NewProcTags
dc.l 0
dc.l NP_Cli,-1
dc.l NP_Priority,TaskPriority
dc.l 0 ;end of tags
***************************************************************************
EndResidentCode: ;end of code copied into allocated memory
***************************************************************************
***************************************************************************
ResidentCodeLength equ EndResidentCode-StartResidentCode
***************************************************************************
* Global data and constants
***************************************************************************
HANDLERPRI equ 100 ;Higher than pesky AMOS
TaskPriority equ 20
ShellPriority equ 0
NULL equ 0
KEYCODE_ESC equ $45
BITDEF BB,TOP,0
BITDEF BB,BOTTOM,1
BITDEF BB,LEFT,2
BITDEF BB,RIGHT,3
DosName dc.b "dos.library",0
IntName dc.b "intuition.library",0
LayName dc.b "layers.library",0
;*****************************************************************
;* Global data structure definitions
STRUCTURE PointerStruct,0
APTR Ptr_Image
LABEL Ptr_Dimensions
BYTE Ptr_Height
BYTE Ptr_Width
BYTE Ptr_XOffset
BYTE Ptr_YOffset
LABEL Ptr_SIZEOF
wd_PtrDimensions equ wd_PtrHeight
STRUCTURE Data,0
APTR MouseChipData
LABEL FirstLibBase
APTR DosBase
APTR IntBase
APTR LayBase
LABEL Sigs
LONG CLISig
LONG UpdateSig
LONG MouseBlankSig
LONG ScreenDepthSig
LONG CloseScreenSig
LABEL EndSigs
NumSigs equ (EndSigs-Sigs)/4
LONG AllSignals ;Logical OR of all signals
APTR Task
APTR ArgPtr
LABEL OldRoutines
APTR OldDisplayBeep
APTR OldCloseScreen
APTR OldScreenDepth
LONG MouseTime ;timeout for mouse blanking
APTR MBlankWindow
APTR MBlankScreen
STRUCT OldPointer,Ptr_SIZEOF
LONG ScreenTime ;for screen blanking
APTR ClickWindow
LONG ClickCount
STRUCT ClickTime,TV_SIZE
APTR InputMsgPort
APTR InputIORequest
Template: dc.b 'M=MBLANK/K/N,'
dc.b 'S=SBLANK/K/N,'
dc.b 'A=ACCELERATION/K/N,'
dc.b 'T=THRESHOLD/K/N,'
dc.b 'CTF=CLICKTOFRONT/K/N,'
dc.b 'CTFB=CLICKTOFRONTBORDER/K/N,'
dc.b 'CTB=CLICKTOBACK/S,'
dc.b 'AFS=ACTIVATEFRONTSCREEN/S,'
dc.b 'CMD=COMMAND/K,'
dc.b 'SUNMOUSE/S,'
dc.b 'NORTHGATE/S,'
dc.b 'NOBEEP/S'
dc.b 0
LABEL Options
LONG MBlankOption
LONG SBlankOption
LONG AccelOption
LONG ThreshOption
LONG CTFOption
LONG ClickBorderOption
LONG CTBOption
LONG ActivateScreenOption
LONG CmdOption
LONG SunMouseOption
LONG NorthgateOption
LONG NoBeepOption
LABEL EndOptions
NumOptions equ (EndOptions-Options)/4
LABEL OptionCaches
LONG MouseBlank
LONG ScreenBlank
LONG Acceleration ; Copies of parameters
LONG Threshold ; ..to avoid having to wait on semaphore
LONG CTF ; ..which could deadlock input handler
LONG CTFB
STRUCT InputInterrupt,IS_SIZE
STRUCT MySemaphore,SS_SIZE
STRUCT ScreenTable,ST_SIZEOF
WORD CurrentX
WORD CurrentY
WORD DampingConstant
BYTE Status ; Various status bits (defined below)
BYTE Padding ; To fill out to even number of bytes
STRUCT ResidentCode,ResidentCodeLength
LABEL Data_SIZEOF
;Bit definitions for Status
BITDEF ST,SBlanked,0
BITDEF ST,MBlanked,1
BITDEF ST,SunMouse,2
BITDEF ST,HandlerInstalled,3
BITDEF ST,InputDeviceOpened,4
BITDEF ST,DoMBlank,5
STRUCTURE MouseData,12
LABEL MouseData_SIZEOF
END