home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Frozen Fish 2: PC
/
frozenfish_august_1995.bin
/
bbs
/
d09xx
/
d0979.lha
/
QMouse
/
qmouse.s
< prev
Wrap
Text File
|
1994-04-04
|
41KB
|
2,052 lines
;QMouse.s
;Written by Dan Babcock
;This source was assembled with Macro68 release 3.
exeobj
objfile 'c:QMouse'
MC68000
multipass
;Set INFO_LEVEL to 1 for full debugging output.
INFO_LEVEL equ 0
;Put a message to the serial port. Used like so:
;
;PUTDEBUG <'Init: called'>
;
;Parameters can be printed out by pushing them on the stack and
;adding the appropriate C printf-style % formatting commands.
PUTDEBUG macro ;<msg>
ifne INFO_LEVEL
movem.l d0-d1/a0-a1,-(sp)
lea .msg\@(pc),a0 ;Point to static format string
lea 16(sp),a1 ;Point to args
bsr KPutFmt
movem.l (sp)+,d0-d1/a0-a1
bra .end\@
.msg\@:
dc.b \1,$a,0
even
.end\@:
endc
endm
MAXQUEUE equ 32
SCREENLISTSIZE equ 32 ;maximum number of screens to keep track of
POINTERLISTSIZE equ 32
HANDLERPRI equ 60 ;priority of input.device handler
TaskPriority equ 21
ShellPriority equ 0
MaxCopperSize equ 500
SysBackground equ $e ;offset into gb_copinit copper list
WindowStart equ $0 ;offset into LOF copper list
DefColor equ $fff ;white
WaitLine equ $16
move.l 4,a6
;Allocate global data structure
move.l #Data_Sizeof,d0
move.l #MEMF_CLEAR,d1
SYS AllocMem
tst.l d0
beq .ErrEnd
move.l d0,a5
lea GlobalPtr(pc),a0
move.l a5,(a0)
;Allocate chip RAM data.
move.l #CData_Sizeof,d0
move.l #MEMF_CLEAR+MEMF_CHIP,d1
SYS AllocMem
move.l d0,ChipData(a5)
beq CleanUp
;Initialize static data
move.b #HANDLERPRI,InputInterrupt+LN_PRI(a5)
move.l a5,InputInterrupt+IS_DATA(a5)
moveq #1,d0
move.l d0,ClickCount(a5)
;Open libraries
lea LibTable(pc),a2
move.l a2,a3
moveq #NumLibs-1,d2
.OLibLoop:
move.w (a2)+,a1
add.l a3,a1
SYS OldOpenLibrary
move.w (a2)+,a0
add.l a5,a0
move.l d0,(a0)
beq CleanUp
dbra d2,.OLibLoop
;Parse command line
lea Template(pc),a0
move.l a0,d1
lea Options(a5),a0
move.l a0,d2
moveq #0,d3 ;no custom rdarg structure
move.l DosBase(a5),a6
SYS ReadArgs
move.l d0,ArgPtr(a5)
bne .ArgsOK
lea BadArgs(pc),a0
move.l a0,d1
SYS VPrintf
bra CleanUp
.ErrEnd: moveq #RETURN_FAIL,d0
rts
.ArgsOK:
move.l 4,a6
;Process QUIT option, if selected.
tst.l QuitOption(a5)
beq .SkipQuit
lea ProcName(pc),a1
SYS FindTask
tst.l d0
beq CleanUp
move.l d0,a1
move.l TC_Userdata(a1),a0
move.l QuitSig(a0),d0
SYS Signal ;tell task to quit
bsr CleanUp
bra .Exit
.SkipQuit:
;If already installed, kill the existing process.
lea ProcName(pc),a1
SYS FindTask
tst.l d0
beq .NotInstalled
move.l d0,a1
move.l TC_Userdata(a1),a0
move.l QuitSig(a0),d0
SYS Signal ;tell task to quit
moveq #26,d2
.Kill: subq.l #1,d2
beq .Exit
move.l DosBase(a5),a6
moveq #2,d1
SYS Delay
lea ProcName(pc),a1
move.l 4,a6
SYS FindTask
tst.l d0
bne .Kill
.NotInstalled:
;Get stack for command.
move.l DosBase(a5),a6
SYS Cli
move.l d0,a0
move.l cli_DefaultStack(a0),d0
lsl.l #2,d0
lea CmdStackSize(pc),a0
move.l d0,(a0)
move.l 4,a6
;Perform relocations.
lea RelocTable(pc),a0
lea ResidentCode(a5),a1 ;destination
lea StartAllocCode(pc),a2
moveq #NumRelocs-1,d0
.RLoop: move.w (a0)+,d2
move.l (a2,d2.w),d1
add.l a1,d1
move.l d1,(a2,d2.w)
dbra d0,.RLoop
;Copy resident part of code into allocated memory
lea StartAllocCode(pc),a0 ;source
; lea ResidentCode(a5),a1 ;destination
move.l #ResidentCodeSize,d0 ;size
SYS CopyMem
SYS CacheClearU ;for 020/030/040
;Start a process
move.l DosBase(a5),a6
lea ResidentCode(a5),a0
lea EntryPoint(pc),a1
move.l a0,(a1)
lea ProcName-StartAllocCode+ResidentCode(a5),a0
lea ProcNamePtr(pc),a1
move.l a0,(a1)
lea NewProcTags(pc),a0
move.l a0,d1
SYS CreateNewProc
;Exit back to CLI
.Exit: moveq #0,d0
rts
RelocTable:
dc.w reloc1-StartAllocCode
dc.w reloc2-StartAllocCode
dc.w reloc3-StartAllocCode
dc.w reloc4-StartAllocCode
EndRelocTable:
NumRelocs equ (EndRelocTable-RelocTable)/2
***************************************************************************
* The following code is copied into allocated memory. *
***************************************************************************
StartAllocCode:
move.l 4,a6
move.l GlobalPtr(pc),a5
lea IntRoutine(pc),a0
move.l a0,InputInterrupt+IS_CODE(a5)
;Initialize damping constant.
move.l AccelOption(a5),d0
beq .NoDamp
move.l d0,a0
move.l (a0),d0
subq.l #1,d0
move.l ThreshOption(a5),d1
beq .DefThresh
move.l d1,a0
move.l (a0),d1
.DefThresh:
addq.l #1,d1
muls.w d0,d1
move.w d1,DampingConstant(a5)
.NoDamp:
;Allocate signals
moveq #NumSigs-1,d2
lea Sigs(a5),a2
.SigLoop: moveq #-1,d0
SYS AllocSignal
tst.l d0
bmi CleanUp
moveq #0,d1
bset d0,d1
move.l d1,(a2)+
dbra d2,.SigLoop
;Initialize semaphore(s)
lea Semaphores(a5),a2
moveq #NumSemaphores-1,d2
.InitSema:
move.l a2,a0
SYS InitSemaphore
lea SS_SIZE(a2),a2
dbra d2,.InitSema
move.l ThisTask(a6),a0
move.l a0,Task(a5)
move.l a5,TC_Userdata(a0)
;Install no-flicker option if selected.
tst.l FlickerOption(a5)
beq .NoFlicker
move.l GraphBase(a5),a0
move.l gb_copinit(a0),a0
move.l a0,OriginalCopInit(a5)
move.l ChipData(a5),a1
lea Copper(a1),a1
move.l a1,a2
move.w #MaxCopperSize/4-1,d0
.CLoop: move.l (a0)+,d1
cmp.l #$008A0000,d1
beq .CopEnd
move.l d1,(a1)+
dbra d0,.CLoop
clr.l FlickerOption(a5)
bra .NoFlicker
.CopEnd: move.l #$01800000,(a1)+
move.l a1,WaitLineAddress(a5)
move.l #$1607FFFE,(a1)+
move.w #$0180,(a1)+
move.l #$008A0000,2(a1)
move.l a1,RealBackground(a5)
move.l a2,cop1lc+_custom
move.l GraphBase(a5),a0
move.l a2,gb_copinit(a0)
cmp.w #color,SysBackground-2(a2)
bne .DefColor
move.w SysBackground(a2),(a1)
bra .NoFlicker
.DefColor:
move.w #DefColor,(a1)
.NoFlicker:
;Patch MANY system routines.
SYS Forbid
lea PatchTable(pc),a2
move.l a2,a3
.Patch: move.w (a2)+,d0 ;get base
beq .EndPatch
move.l (a5,d0.w),a1 ;library base to patch
move.w (a2)+,d0 ;get minimum library version
cmp.w LIB_VERSION(a1),d0
bls .VersionOK
addq.l #6,a2
bra .Patch
.VersionOK:
move.w (a2)+,d0 ;get offset to new routine
lea (a3,d0.w),a0
move.l a0,d0 ;new routine address
move.w (a2)+,a0 ;_LVO offset
SYS SetFunction
move.w (a2)+,d1
move.l d0,(a5,d1.w)
bra .Patch
.EndPatch:
SYS Permit
;Create an IORequest structure
SYS CreateMsgPort
move.l d0,InputMsgPort(a5)
beq CleanUp
move.l d0,a0
moveq #IOSTD_SIZE,d0
SYS CreateIORequest
move.l d0,InputIORequest(a5)
beq CleanUp
;Perform NoClick, if desired.
move.l NoClickOption(a5),d2
beq .Click
move.l d2,a0
move.l (a0),d2
.Click: moveq #0,d3
moveq #3,d4
.ClickLoop:
lea TrackName(pc),a0 ;device name
move.l d3,d0 ;unit number
move.l InputIORequest(a5),a1 ;IO request
moveq #0,d1 ;flags
SYS OpenDevice
tst.l d0
bne .ECLoop
move.l InputIORequest(a5),a1 ;IO request
move.l IO_UNIT(a1),a0
btst d3,d2
beq .SkipNoClick
bset #TDPB_NOCLICK,TDU_PUBFLAGS(a0)
.SkipNoClick:
tst.l VerifyOption(a5)
beq .NoVerify
bset #1,TDU_PUBFLAGS(a0)
.NoVerify:
tst.l NoVerifyOption(a5)
beq .SkipVerify
bclr #1,TDU_PUBFLAGS(a0)
.SkipVerify:
SYS CloseDevice
.ECLoop: addq.l #1,d3
dbra d4,.ClickLoop
;Handle 'STAR' option.
tst.l StarOption(a5)
beq .NoStar
move.l DosBase(a5),a0
move.l dl_Root(a0),a0
bset #0,rn_Flags(a0)
.NoStar:
;Open the input.device
lea InputName(pc),a0 ;device name
moveq #0,d0 ;unit number
move.l InputIORequest(a5),a1 ;IO request
moveq #0,d1 ;flags
SYS OpenDevice
tst.l d0
bne CleanUp
;Install virtical blank routine if needed.
tst.l SunMouseOption(a5)
beq .SkipVBL
moveq #INTB_VERTB,d0
lea VBlankServer(a5),a1
move.l a5,IS_DATA(a1)
lea VBlankRoutine(pc),a0
move.l a0,IS_CODE(a1)
move.b #NT_INTERRUPT,LN_TYPE(a1)
SYS AddIntServer
bset #STB_IntInstalled,Status(a5)
.SkipVBL:
;Install input handler
move.l InputIORequest(a5),a1
move.w #IND_ADDHANDLER,IO_COMMAND(a1)
lea InputInterrupt(a5),a0
move.l a0,IO_DATA(a1)
SYS DoIO
tst.l d0
bne CleanUp
st HandlerInstalled(a5)
;Wait for signal(s)
Wait:
tst.l TaskQueue(a5)
bne .DoTasks
lea Sigs(a5),a0
move.l (a0)+,d0
moveq #NumSigs-2,d1
.. add.l (a0)+,d0
dbra d1,..
move.l 4,a6
SYS Wait
move.l d0,d7
move.l d7,d1
and.l QuitSig(a5),d1
bne SafeCleanUp
move.l d7,d1
and.l FuncSig(a5),d1
beq Wait
.DoTasks: move.l IntBase(a5),a6
lea TaskQueue(a5),a4
.TaskLoop:
move.l (a4),d0
beq Wait
clr.l (a4)+
move.l d0,a0
bsr GetAllSemaphores
jsr (a0)
bsr FreeAllSemaphores
bra .TaskLoop
BlankScreenTags:
dc.l SA_Depth,1
dc.l SA_Colors
reloc4: dc.l .ColorSpec-StartAllocCode
dc.l 0 ;end tags
.ColorSpec:
dc.w 0,0,0,0
dc.w 1,0,0,0
dc.w -1
BlankScreenWindowTags:
dc.l WA_CustomScreen
BlankScreenTagPtr:
dc.l 0
dc.l 0 ;end tags
DoBlankScreen:
move.l BlankScreenPtr(a5),d0
beq .Blank
move.l d0,a0
SYS ScreenToFront
move.l BlankScreenWindowPtr(a5),d0
beq _RTS1
move.l d0,a0
jmp _LVOActivateWindow(a6)
.Blank: sub.l a0,a0
lea BlankScreenTags(pc),a1
SYS OpenScreenTagList
move.l d0,BlankScreenPtr(a5)
beq _RTS1
lea BlankScreenTagPtr(pc),a0
move.l d0,(a0)
sub.l a0,a0
lea BlankScreenWindowTags(pc),a1
SYS OpenWindowTagList
move.l d0,BlankScreenWindowPtr(a5)
beq _RTS1
move.l d0,a0
move.l ChipData(a5),a1
; lea ZeroMouse(a1),a1 ;not needed
moveq #1,d0 ;height
moveq #16,d1 ;width
moveq #0,d2 ;xoffset
moveq #0,d3 ;yoffset
pea DoBlankScreen(pc)
move.l OldSetPointer(a5),-(sp)
_RTS1: rts
DoRestoreScreen:
move.l BlankScreenPtr(a5),d2
beq _RTS1
clr.l BlankScreenPtr(a5)
move.l BlankScreenWindowPtr(a5),d0
beq .SkipWinClose
clr.l BlankScreenWindowPtr(a5)
move.l d0,a0
SYS CloseWindow
.SkipWinClose:
move.l d2,a0
jmp _LVOCloseScreen(a6)
CTF: bsr GetWindow
tst.l d0
beq _RTS1
move.l CTFOption(a5),a2
move.l (a2),d1
cmp.l #1,d1
bhi .MoreThanOne
bra DoWindowToFront
.MoreThanOne:
cmp.l ClickWindow(a5),d0
beq .SameWindow
move.l d0,ClickWindow(a5)
moveq #1,d0
move.l d0,ClickCount(a5)
.Time: bsr GetIBase
move.l ib_Seconds(a6),ClickTime+TV_SECS(a5)
move.l ib_Micros(a6),ClickTime+TV_MICRO(a5)
bra FreeIBase
.SameWindow:
;Check to see whether MaxClickDelay has been exceeded. If not, increment
;ClickCount and compare with (CTFOption). If equal, do a WindowToFront.
;Window under pointer in D0.
push d0
move.l ClickTime+TV_SECS(a5),d0
move.l ClickTime+TV_MICRO(a5),d1
bsr GetIBase
move.l ib_Seconds(a6),d2
move.l ib_Micros(a6),d3
bsr FreeIBase
SYS DoubleClick
tst.l d0
beq .TimeExceeded
addq.l #1,ClickCount(a5)
move.l CTFOption(a5),a0
move.l (a0),d0
cmp.l ClickCount(a5),d0
bhi .NeedMoreClicks
clr.l ClickCount(a5)
pop d0
bra DoWindowToFront
.TimeExceeded:
moveq #1,d0
move.l d0,ClickCount(a5)
.NeedMoreClicks:
pop d0
bra .Time
CTB: bsr GetWindow
tst.l STBOption(a5)
bne .FlipScreen
tst.l d0
beq .FlipScreen
move.l d0,a1
move.l wd_Flags(a1),d2
and.l #WFLG_BACKDROP,d2
bne .FlipScreen
;Is this the only window on this screen, except for backdrop windows?
move.l wd_WScreen(a1),a1
move.l sc_FirstWindow(a1),a1
.BackLoop:
cmp.l a1,d0
beq .EBackLoop
move.l wd_Flags(a1),d2
and.l #WFLG_BACKDROP,d2
beq .FlipWindow
.EBackLoop:
move.l (a1),a1
move.l a1,d2
bne .BackLoop
.FlipScreen:
tst.l d1
beq .End
move.l d1,a0
jmp _LVOScreenToBack(a6)
.FlipWindow:
move.l d0,a0
jmp _LVOWindowToBack(a6)
.End: rts
PopCLI:
;Execute the desired command
move.l a6,-(sp)
move.l DosBase(a5),a6
move.l CmdOption(a5),d1
beq .End
lea .Tags(pc),a0
move.l a0,d2 ;tags
;Important fix: free the semaphores (we don't need them here and they can and
;do lead to deadlocks).
bsr FreeAllSemaphores
SYS SystemTagList
bsr GetAllSemaphores
tst.l NoWBenchToFrontOption(a5)
bne .End
move.l IntBase(a5),a6
SYS WBenchToFront
.End: move.l (sp)+,a6
rts
.Tags: dc.l SYS_UserShell,0
dc.l NP_Priority,ShellPriority
dc.l NP_StackSize
CmdStackSize:
dc.l 0
dc.l 0 ;end of tag list
SafeCleanUp:
;Make sure the SetFunction'ed vectors are still intact.
lea PatchTable(pc),a0
move.l a0,a2
.Safe: move.w (a0)+,d0
beq CleanUp
move.l (a5,d0.w),a1 ;library base
addq.l #2,a0 ;skip version #
move.w (a0)+,d0
lea (a2,d0.w),a3 ;address of new routine
move.w (a0)+,d0 ;_LVO offset
move.w (a0)+,d1 ;Old vector
tst.l (a5,d1.w)
beq .Safe
cmp.l 2(a1,d0.w),a3
beq .Safe
;A routine has been patched by another program. Alert the user.
;a1 is lib pointer, d0.w is routine offset.
ext.l d0
neg.l d0
move.l d0,-(sp)
move.l LN_NAME(a1),-(sp)
move.l sp,a3
move.l IntBase(a5),a6
sub.l a0,a0
lea PatchAlert(pc),a1
sub.l a2,a2
SYS EasyRequestArgs
addq.l #8,sp
bra Wait
PatchAlert:
dc.l es_SIZEOF
dc.l 0
reloc1: dc.l TitleText-StartAllocCode
reloc2: dc.l AlertText-StartAllocCode
reloc3: dc.l OkayText-StartAllocCode
TitleText:
dc.b 'QMouse message',0
AlertText:
dc.b 'Can''t quit or modify parameters. Another program',$a
dc.b 'has patched the same OS routines!',$a
dc.b $a
dc.b 'Technical information:',$a
dc.b 'Library: %s',$a
dc.b 'Offset: -$%lx',$a
dc.b '(There may be others)',0
OkayText:
dc.b 'OK',0
even
CleanUp:
;Enter with global ptr in A5
move.l 4,a6
;Remove interrupt routine, if installed.
btst #STB_IntInstalled,Status(a5)
beq .SkipIntRemove
moveq #INTB_VERTB,d0
lea VBlankServer(a5),a1
SYS RemIntServer
.SkipIntRemove:
;Remove input handler, if installed.
tst.b HandlerInstalled(a5)
beq .SkipHand
move.l InputIORequest(a5),a1
move.w #IND_REMHANDLER,IO_COMMAND(a1)
lea InputInterrupt(a5),a0
move.l a0,IO_DATA(a1)
SYS DoIO
.SkipHand:
tst.l OldCloseScreen(a5)
beq .SkipRestore
bsr RestoreMouse
move.l IntBase(a5),a6
bsr DoRestoreScreen
move.l 4,a6
;Restore original vectors.
lea PatchTable(pc),a2
.RestoreVecs:
move.w (a2),d0
beq .SkipRestore
addq.l #6,a2 ;skip new routine info
move.l (a5,d0.w),a1 ;get library base
move.w (a2)+,a0 ;get _LVO
move.w (a2)+,d0
move.l (a5,d0.w),d0 ;old routine
beq .RestoreVecs
SYS SetFunction
bra .RestoreVecs
.SkipRestore:
;Delay for 1/10 second to ensure that no-one is using the patch code.
move.l DosBase(a5),d0
beq .SkipFreeArg
move.l d0,a6
moveq #5,d1
SYS Delay
;Free argument structure
move.l ArgPtr(a5),d1
beq .SkipFreeArg
SYS FreeArgs
.SkipFreeArg:
move.l 4,a6
;Free signals
lea Sigs(a5),a2
moveq #NumSigs-1,d2
.SigLoop: move.l (a2)+,d1
beq .NextSig
moveq #-1,d0
.BitLoop: addq.l #1,d0
btst d0,d1
beq .BitLoop
SYS FreeSignal
.NextSig: dbra d2,.SigLoop
;Remove flicker option, if selected.
tst.l FlickerOption(a5)
beq .SkipFlicker
move.l OriginalCopInit(a5),a0
move.l GraphBase(a5),a2
move.l gb_copinit(a2),a1
.CLoop: move.l (a1)+,(a0)+
cmp.l #$008A0000,(a0)
bne .CLoop
move.l OriginalCopInit(a5),gb_copinit(a2)
move.l OriginalCopInit(a5),cop1lc+_custom
.SkipFlicker:
;Close libraries
lea LibTable+2(pc),a2
moveq #NumLibs-1,d2
.CLibLoop:
move.w (a2),a0
add.l a5,a0
tst.l (a0)
beq .SkipClose
move.l (a0),a1
SYS CloseLibrary
.SkipClose:
addq.l #4,a2
dbra d2,.CLibLoop
;Close input.device
move.l InputIORequest(a5),d0
beq .SkipCloseDev
move.l d0,a1
tst.b IO_ERROR(a1) ;was there an error?
bne .SkipCloseDev ;yes, don't close
SYS CloseDevice
.SkipCloseDev:
;Delete IORequest structure
move.l InputIORequest(a5),a0
SYS DeleteIORequest
move.l InputMsgPort(a5),a0
SYS DeleteMsgPort
;Free chip data.
move.l ChipData(a5),d0
beq .SkipChipData
move.l d0,a1
move.l #CData_Sizeof,d0
SYS FreeMem
.SkipChipData:
;Deallocate global structure. Note that this code is (sometimes) executed
;within the memory that we are freeing, so we are careful to terminate with
;a JMP.
move.l a5,a1
move.l #Data_Sizeof,d0
jmp _LVOFreeMem(a6)
;Semaphore routines
GetIBase:
; PUTDEBUG <'GetIBase: Called'>
movem.l d0-d1/a0-a1/a5-a6,-(sp)
move.l GlobalPtr(pc),a5
move.l IntBase(a5),a6
moveq #0,d0
SYS LockIBase
move.l d0,IBaseLock(a5)
movem.l (sp)+,d0-d1/a0-a1/a5-a6
; PUTDEBUG <'GetIBase: Done'>
rts
FreeIBase:
; PUTDEBUG <'FreeIBase'>
movem.l d0-d1/a0-a1/a6,-(sp)
move.l GlobalPtr(pc),a0
move.l IntBase(a0),a6
move.l IBaseLock(a0),a0
SYS UnlockIBase
movem.l (sp)+,d0-d1/a0-a1/a6
rts
GetSemaphore:
PUTDEBUG <'GetSemaphore: Called'>
movem.l a0/a6,-(sp)
move.l GlobalPtr(pc),a0
lea MySemaphore(a0),a0
_GS: move.l 4,a6
SYS ObtainSemaphore
movem.l (sp)+,a0/a6
PUTDEBUG <'GetSemaphore: Done'>
rts
FreeSemaphore:
movem.l a0/a6,-(sp)
move.l GlobalPtr(pc),a0
lea MySemaphore(a0),a0
_FS: move.l 4,a6
SYS ReleaseSemaphore
movem.l (sp)+,a0/a6
PUTDEBUG <'FreeSemaphore'>
rts
GetCloseWindowSemaphore:
PUTDEBUG <'GetCloseWindowSemaphore'>
movem.l a0/a6,-(sp)
move.l GlobalPtr(pc),a0
lea CloseWindowSemaphore(a0),a0
bra _GS
FreeCloseWindowSemaphore:
PUTDEBUG <'FreeCloseWindowSemaphore'>
movem.l a0/a6,-(sp)
move.l GlobalPtr(pc),a0
lea CloseWindowSemaphore(a0),a0
bra _FS
GetCloseScreenSemaphore:
PUTDEBUG <'GetCloseScreenSemaphore'>
movem.l a0/a6,-(sp)
move.l GlobalPtr(pc),a0
lea CloseScreenSemaphore(a0),a0
bra _GS
FreeCloseScreenSemaphore:
PUTDEBUG <'FreeCloseScreenSemaphore'>
movem.l a0/a6,-(sp)
move.l GlobalPtr(pc),a0
lea CloseScreenSemaphore(a0),a0
bra _FS
GetCloseWBSemaphore:
PUTDEBUG <'GetCloseWBSemaphore'>
movem.l a0/a6,-(sp)
move.l GlobalPtr(pc),a0
lea CloseWBSemaphore(a0),a0
bra _GS
FreeCloseWBSemaphore:
PUTDEBUG <'FreeCloseWBSemaphore'>
movem.l a0/a6,-(sp)
move.l GlobalPtr(pc),a0
lea CloseWBSemaphore(a0),a0
bra _FS
GetAllSemaphores:
;The order matters! The sems must be allocated in this order to avoid
;the "deadly embrace".
bsr GetCloseWBSemaphore
bsr GetCloseScreenSemaphore
bsr GetCloseWindowSemaphore
bra GetSemaphore
FreeAllSemaphores:
;We can free in any order (provided that we are freeing ALL of them).
bsr FreeSemaphore
bsr FreeCloseWindowSemaphore
bsr FreeCloseScreenSemaphore
bra FreeCloseWBSemaphore
LibTable: dc.w DosName-LibTable
dc.w DosBase
dc.w IntName-LibTable
dc.w IntBase
dc.w LayersName-LibTable
dc.w LayersBase
dc.w GraphName-LibTable
dc.w GraphBase
dc.w UtilityName-LibTable
dc.w _UtilityBase
EndLibTable:
NumLibs equ (EndLibTable-LibTable)/4
;****************** SetFunction'ed routines ***************
patch macro
dc.w \1
dc.w \3 ;minimum library version
dc.w New\2-PatchTable
dc.w _LVO\2
dc.w Old\2
endm
PatchTable:
patch IntBase,SetWindowPointerA,39
patch IntBase,OpenWindowTagList,39
patch IntBase,CloseScreen,37
patch IntBase,CloseWorkBench,37
patch IntBase,CloseWindow,37
patch IntBase,SetPointer,37
patch IntBase,ClearPointer,37
patch IntBase,DisplayBeep,37
dc.w 0
NewDisplayBeep:
PUTDEBUG <'NewDisplayBeep'>
move.l GlobalPtr(pc),a1
tst.l BeepOption(a1)
bne .SkipBeep
move.l OldDisplayBeep(a1),-(sp)
.SkipBeep:
rts
NewOpenWindowTagList:
;Enter with NewWindow in A0, taglist in A1
PUTDEBUG <'NewOpenWindowTagList'>
move.l a1,-(sp)
pea .HandlePointer(pc)
subq.l #8,sp
move.l a0,(sp)
move.l GlobalPtr(pc),a0
move.l OldOpenWindowTagList(a0),4(sp)
move.l (sp)+,a0
.End: rts
.RestoreD0:
move.l (sp)+,d0
rts
.HandlePointer:
move.l (sp)+,a1
tst.l d0
beq .End
move.l d0,a0
move.l d0,-(sp)
pea .RestoreD0(pc)
; bra NewSetWindowPointerA
NewSetWindowPointerA:
;Enter with:
;A0 - Window
;A1 - taglist
SaveRegs setrl d4-d5/a0-a6
PUTDEBUG <'NewSetWindowPointerA'>
bsr GetSemaphore
movem.l SaveRegs,-(sp)
move.l GlobalPtr(pc),a5
lea PointerList(a5),a2
;Find if window is already in table and find empty spot.
moveq #POINTERLISTSIZE-1,d4
sub.l a3,a3
.WinSearch:
move.l pt_Window(a2),d5
bne .SkipSave
move.l a2,a3
.SkipSave:
cmp.l d5,a0
beq .Found
lea pt_Sizeof(a2),a2
dbra d4,.WinSearch
move.l a3,a2
move.l a2,d4
beq .CallOld ;no room in table, so forget it
.Found:
;Store the taglist information
move.l a0,a3 ;window
move.l a1,a4 ;taglist
move.l a0,pt_Window(a2)
st TagVersion(a2)
move.l _UtilityBase(a5),a6
;Check for WA_BusyPointer.
move.l #WA_BusyPointer,d0
move.l a4,a0
SYS FindTagItem
tst.l d0
beq .NotBusy
move.l d0,a0
IFNE INFO_LEVEL
move.l 4(a0),-(sp)
move.l (a0),-(sp)
PUTDEBUG <'WA_BusyPointer=%lx,%lx '>
addq.l #8,sp
ENDC
move.l (a0),(a2)
move.l 4(a0),4(a2)
beq .NotBusy
clr.l 8(a2)
bra .CallOld
.NotBusy:
;Check for WA_Pointer.
move.l #WA_Pointer,d0
move.l a4,a0
SYS FindTagItem
tst.l d0
beq .Nothing
move.l d0,a0
IFNE INFO_LEVEL
move.l 4(a0),-(sp)
move.l (a0),-(sp)
PUTDEBUG <'WA_Pointer=%lx,%lx '>
addq.l #8,sp
ENDC
move.l (a0),(a2)
move.l 4(a0),4(a2)
clr.l 8(a2)
bra .CallOld
.Nothing:
;Don't understand the taglist.
PUTDEBUG <'Don''t grok SetWindowPointerA taglist!'>
clr.l pt_Window(a2)
.CallOld: cmp.l MBlankWindow(a5),a3
beq .End
;Call old SetWindowPointerA
movem.l (sp)+,SaveRegs
subq.l #8,sp
move.l a0,(sp)
move.l GlobalPtr(pc),a0
move.l OldSetWindowPointerA(a0),4(sp)
move.l (sp)+,a0
bra FreeSemaphore
.End: movem.l (sp)+,SaveRegs
bra FreeSemaphore
NewSetPointer:
PUTDEBUG <'NewSetPointer'>
bsr GetSemaphore
movem.l d4-d5/a2-a3/a5,-(sp)
move.l GlobalPtr(pc),a5
cmp.l ChipData(a5),a1 ;special check to ward off sneaky code like
beq .End1 ;reqtools
lea PointerList(a5),a2
;Find if window is already in table and find empty spot.
moveq #POINTERLISTSIZE-1,d4
sub.l a3,a3
.WinSearch:
move.l pt_Window(a2),d5
bne .SkipSave
move.l a2,a3
.SkipSave:
cmp.l d5,a0
beq .Found
lea pt_Sizeof(a2),a2
dbra d4,.WinSearch
move.l a3,a2
move.l a2,d4
beq .End ;no room in table, so forget it
.Found: movem.l d0-d3/a0-a1,(a2)
clr.b TagVersion(a2)
.End: cmp.l MBlankWindow(a5),a0
beq .End1
movem.l (sp)+,d4-d5/a2-a3/a5
subq.l #8,sp
move.l a0,(sp)
move.l GlobalPtr(pc),a0
move.l OldSetPointer(a0),4(sp)
move.l (sp)+,a0
bra FreeSemaphore
.End1: movem.l (sp)+,d4-d5/a2-a3/a5
bra FreeSemaphore
NewClearPointer:
PUTDEBUG <'NewClearPointer'>
bsr GetSemaphore
move.l GlobalPtr(pc),a1
lea PointerList(a1),a1
moveq #POINTERLISTSIZE-1,d0
.ClearLoop:
cmp.l pt_Window(a1),a0
beq .Found
lea pt_Sizeof(a1),a1
dbra d0,.ClearLoop
bra .End
.Found: clr.l pt_Window(a1)
.End: move.l GlobalPtr(pc),a1
cmp.l MBlankWindow(a1),a0
beq .End1
move.l OldClearPointer(a1),-(sp)
.End1: bra FreeSemaphore
NewCloseWorkBench:
PUTDEBUG <'NewCloseWorkBench'>
bsr GetCloseWBSemaphore
SYS OpenWorkBench ;get workbench screen ptr in d0
tst.l d0
beq FreeCloseWBSemaphore
move.l d0,a0
move.l GlobalPtr(pc),a1
move.l OldCloseWorkBench(a1),d1
pea .Free(pc)
bra CloseScreenCode
.Free: bra FreeCloseWBSemaphore
NewCloseScreen:
PUTDEBUG <'NewCloseScreen'>
bsr GetCloseScreenSemaphore
move.l GlobalPtr(pc),a1
move.l OldCloseScreen(a1),d1
pea .Free(pc)
bra CloseScreenCode
.Free: bra FreeCloseScreenSemaphore
CloseScreenCode:
;Code shared by NewCloseScreen and NewCloseWorkBench
;Enter with Screen in A0, Global in A1, old vector in D1
bsr GetSemaphore
lea ScreenList(a1),a1
moveq #SCREENLISTSIZE-1,d0
.Loop: cmp.l (a1),a0
beq .Match
addq.l #8,a1
dbra d0,.Loop
.End: bsr FreeSemaphore
move.l GlobalPtr(pc),a1
pea .ExtraClose(pc)
move.l d1,-(sp)
rts
.Match: clr.l (a1)
bra .End
.ExtraClose:
move.l GlobalPtr(pc),a0
bsr GetIBase
move.l ib_FirstScreen(a6),CurrentTopScreen(a0)
move.l ib_ActiveScreen(a6),CurrentActiveScreen(a0)
bsr FreeIBase
bra RestoreWindow
NewCloseWindow:
PUTDEBUG <'NewCloseWindow'>
move.l GlobalPtr(pc),a1
bsr GetCloseWindowSemaphore
bsr GetSemaphore
pea .ExtraClose(pc)
push a0
SYS ClearPointer
pop a0
move.l GlobalPtr(pc),a1
cmp.l MBlankWindow(a1),a0
bne .SkipClearMBW
clr.l MBlankWindow(a1)
.SkipClearMBW:
cmp.l ClickWindow(a1),a0
bne .SkipClearCW
clr.l ClickWindow(a1)
.SkipClearCW:
lea ScreenList+4(a1),a1
moveq #SCREENLISTSIZE-1,d0
.Loop: cmp.l (a1),a0
beq .Match
addq.l #8,a1
dbra d0,.Loop
.End: bsr FreeSemaphore
move.l GlobalPtr(pc),a1
move.l OldCloseWindow(a1),-(sp)
rts
.Match: clr.l -4(a1)
bra .End
.ExtraClose:
move.l GlobalPtr(pc),a0
bsr GetIBase
move.l ib_ActiveWindow(a6),CurrentActiveWindow(a0)
bsr FreeIBase
bra FreeCloseWindowSemaphore
;****************** End of SetFunction'ed routines ***************
RememberWindow:
;No OS calls
;Enter with Screen in A0, Window in A2
movem.l d0-d1/a0-a2/a5,-(sp)
move.l GlobalPtr(pc),a5
;Sanity checks
move.l a0,d0
beq .End
move.l a2,d0
beq .End
lea ScreenList(a5),a1
moveq #SCREENLISTSIZE-1,d0
.ScLoop: cmp.l (a1),a0
beq .Match
addq.l #8,a1
dbra d0,.ScLoop
;Screen not found. Add to screen list.
lea ScreenList(a5),a1
moveq #SCREENLISTSIZE-1,d0
.AddLoop: tst.l (a1)
beq .Match
addq.l #8,a1
dbra d0,.AddLoop
bra .End ;table is full
.Match:
move.l a0,(a1)+ ;screen
move.l a2,(a1) ;currently activated window
.End: movem.l (sp)+,d0-d1/a0-a2/a5
rts
RestoreWindow:
movem.l a1-a2,-(sp)
move.l GlobalPtr(pc),a1
lea TaskRestoreWindow(pc),a2
bsr DoFunc
movem.l (sp)+,a1-a2
rts
TaskRestoreWindow:
;This routine restores (re-activates) the previously activated window for
;this screen.
movem.l d0-d2/a0-a2/a6,-(sp)
move.l GlobalPtr(pc),a0
tst.l NoActivateOption(a0)
bne .End
lea ScreenList(a0),a2
move.l IntBase(a0),a6
bsr GetIBase
move.l ib_FirstScreen(a6),d2
bsr FreeIBase
tst.l d2
beq .End ;sanity check
move.l d2,CurrentTopScreen(a0)
tst.l PubChangeOption(a0)
beq .NoPubChange
;If the screen is public, make it the default public screen.
SYS LockPubScreenList
.PubLoop: tst.l d0
beq .EndPubChange
move.l d0,a0
cmp.l psn_Screen(a0),d2
beq .FoundScreen
move.l LN_SUCC(a0),d0
bra .PubLoop
.FoundScreen:
move.l LN_NAME(a0),a0
SYS SetDefaultPubScreen
.EndPubChange:
SYS UnlockPubScreenList
.NoPubChange:
move.l d2,a0
moveq #SCREENLISTSIZE-1,d0
.Loop: cmp.l (a2),a0
beq .Match
addq.l #8,a2
dbra d0,.Loop
move.l sc_FirstWindow(a0),a0 ;default window
move.l a0,d0
beq .End ;sanity check
bra .SkipMatch
.Match:
move.l 4(a2),a0
.SkipMatch:
SYS ActivateWindow
move.l GlobalPtr(pc),a0
bsr GetIBase
move.l ib_ActiveScreen(a6),CurrentActiveScreen(a0)
bsr FreeIBase
.End: movem.l (sp)+,d0-d2/a0-a2/a6
rts
;Get window associated with current mouse position.
;Returns Window in D0 and screen in D1.
GetWindow:
movem.l d4/a0-a1/a4-a6,-(sp)
move.l GlobalPtr(pc),a5
move.l LayersBase(a5),a6
move.l IntBase(a5),a4
bsr GetIBase
move.l ib_FirstScreen(a4),d4
.ScLoop: tst.l d4
beq .ErrEnd
move.l d4,a0
move.l sc_NextScreen(a0),d4
move.w sc_MouseX(a0),d0
bmi .ScLoop
move.w sc_MouseY(a0),d1
bmi .ScLoop
push a0
lea sc_LayerInfo(a0),a0
bsr FreeIBase
SYS WhichLayer
pop d1
tst.l d0
beq .End
move.l d0,a0
move.l lr_Window(a0),d0
.End: movem.l (sp)+,d4/a0-a1/a4-a6
rts
.ErrEnd: bsr FreeIBase
moveq #0,d0
moveq #0,d1
bra .End
ActivateWindow:
;Activate the window under the mouse pointer.
;Enter with IntuitionBase in A6
bsr GetWindow
tst.l d0
beq .End
move.l d0,a0
bsr GetIBase
move.l ib_ActiveWindow(a6),d0
bsr FreeIBase
cmp.l d0,a0
beq .End
tst.l wd_FirstRequest(a0)
bne .End
SYS ActivateWindow
.End: rts
DoWindowToFront:
;Perform a WindowToFront on the window in D0.
;Enter with IntuitionBase in A6.
tst.l d0
beq .End1
movem.l d0-d1/a0-a1/a6,-(sp)
move.l d0,a0
move.l wd_WLayer(a0),a1
move.l a1,d0
beq .End
move.l lr_ClipRect(a1),a1
move.l a1,d0
beq .End
tst.l (a1)
beq .End
move.l wd_Flags(a0),d0
and.l #WFLG_BACKDROP,d0
bne .End
SYS WindowToFront
.End: movem.l (sp)+,d0-d1/a0-a1/a6
.End1: rts
BlankMouse:
movem.l d0-d3/a0-a1/a5-a6,-(sp)
move.l GlobalPtr(pc),a5
move.l IntBase(a5),a6
bsr GetIBase
move.l ib_ActiveWindow(a6),d0
bsr FreeIBase
tst.l d0
beq .End
cmp.l MBlankWindow(a5),d0
beq .End
bsr RestoreMouse
move.l d0,MBlankWindow(a5)
move.l d0,a0
move.l ChipData(a5),a1
; lea ZeroMouse(a1),a1 ;not needed
moveq #1,d0 ;height
moveq #16,d1 ;width
moveq #0,d2 ;xoffset
moveq #0,d3 ;yoffset
pea .End(pc)
move.l OldSetPointer(a5),-(sp)
rts
.End: movem.l (sp)+,d0-d3/a0-a1/a5-a6
rts
RestoreMouse:
movem.l d0-d1/a0-a2/a5-a6,-(sp)
move.l GlobalPtr(pc),a5
move.l IntBase(a5),a6
move.l MBlankWindow(a5),d0
beq .End
;Look for window in pointer table. If present, do a SetPointer or SetWindowPointerA
;to restore the custom pointer. Otherwise call ClearPointer.
move.l d0,a0
clr.l MBlankWindow(a5)
lea PointerList(a5),a1
moveq #POINTERLISTSIZE-1,d0
.WinLoop: cmp.l pt_Window(a1),a0
beq .Found
lea pt_Sizeof(a1),a1
dbra d0,.WinLoop
pea .End(pc)
move.l OldClearPointer(a5),-(sp)
rts
.End: movem.l (sp)+,d0-d1/a0-a2/a5-a6
rts
.Found: move.l a1,a2
tst.b TagVersion(a2)
beq .NoTag
;Call SetWindowPointerA to restore the custom pointer.
move.l pt_Window(a2),a0
pea .End(pc)
move.l OldSetWindowPointerA(a5),-(sp)
rts
.NoTag: movem.l (a2),d0-d3/a0-a1
pea .End(pc)
move.l OldSetPointer(a5),-(sp)
rts
;***************************************************************************
;Start of input handler code
;***************************************************************************
BlankScreen:
;Enter with global in A1.
bset #STB_SBlanked,Status(a1)
lea DoBlankScreen(pc),a2
bra DoFunc
RestoreScreen:
;Enter with global in A1 AND input event in A0.
move.l ie_TimeStamp(a0),ScreenTime(a1)
bclr #STB_SBlanked,Status(a1)
beq _RTS
lea DoRestoreScreen(pc),a2
; bra DoFunc
DoFunc:
;Enter with pointer to routine in A2
;Enter with global ptr in A1.
movem.l d0-d1/a0-a1/a6,-(sp)
lea TaskQueue(a1),a0
moveq #MAXQUEUE-1,d0
.. tst.l (a0)+
dbeq d0,..
bne .End
move.l a2,-(a0)
move.l FuncSig(a1),d0
move.l Task(a1),a1
move.l 4,a6
SYS Signal
.End: movem.l (sp)+,d0-d1/a0-a1/a6
_RTS: rts
;**************************** Input handler *********************************
IntRoutine:
movem.l d2/a2/a6,-(sp)
move.l a0,-(sp)
move.l IntBase(a1),a6
bsr GetIBase
;Handle NoFlicker option
tst.l FlickerOption(a1)
beq .SkipFlick
move.l GraphBase(a1),a0
move.l gb_LOFlist(a0),a2
move.l WaitLineAddress(a1),a0
cmp.b #WaitLine-1,WindowStart(a2)
blo .DisableNF
move.b #WaitLine,(a0)
bra .SkipDisableNF
.DisableNF:
clr.b (a0)
.SkipDisableNF:
move.l GraphBase(a1),a0
move.l gb_copinit(a0),a0
cmp.w #color,SysBackground-2(a0)
bne .DefColor
move.w SysBackground(a0),d0
move.l RealBackground(a1),a0
move.w d0,(a0)
bra .SkipColor
.DefColor:
move.l RealBackground(a1),a0
move.w #DefColor,(a0)
.SkipColor:
move.l (sp),a0
.SkipFlick:
;Check for change in active screen.
;But first: attempt to obtain the semaphores
movem.l a0-a1/a6,-(sp)
move.l 4,a6
lea Semaphores(a1),a2
moveq #NumSemaphores-1,d2
.Attempt: move.l a2,a0
SYS AttemptSemaphore
tst.l d0
beq .AttemptFailed
lea SS_SIZE(a2),a2
dbra d2,.Attempt
movem.l (sp)+,a0-a1/a6
bra .CheckScreenStuff
.AttemptFailed:
moveq #2,d0
sub.w d2,d0
bmi .NoneSucceeded
move.l a2,a0
.CleanUp: lea -SS_SIZE(a0),a0
SYS ReleaseSemaphore
dbra d0,.CleanUp
.NoneSucceeded:
movem.l (sp)+,a0-a1/a6
bra .NoSemaphore
.CheckScreenStuff:
move.l CurrentActiveScreen(a1),d0
cmp.l ib_ActiveScreen(a6),d0
beq .SameActiveScreen
push a0
move.l CurrentActiveScreen(a1),a0
move.l CurrentActiveWindow(a1),a2
bsr RememberWindow
pop a0
.SameActiveScreen:
;Check for change in top screen.
move.l CurrentTopScreen(a1),d0
beq .CSZ
cmp.l ib_FirstScreen(a6),d0
beq .SkipRW
push a0
move.l CurrentActiveScreen(a1),a0
move.l CurrentActiveWindow(a1),a2
bsr RememberWindow
pop a0
lea TaskRestoreWindow(pc),a2
bsr DoFunc
.CSZ: move.l ib_FirstScreen(a6),CurrentTopScreen(a1)
.SkipRW: move.l ib_ActiveWindow(a6),CurrentActiveWindow(a1)
move.l ib_ActiveScreen(a6),CurrentActiveScreen(a1)
bsr FreeAllSemaphores
.NoSemaphore:
;If screen is blanked, re-blank (actually just move the blanking screen to the
;front)
btst #STB_SBlanked,Status(a1)
beq .SkipReBlank
move.l ib_FirstScreen(a6),d0
cmp.l BlankScreenPtr(a1),d0
beq .SkipReBlank
bsr BlankScreen
.SkipReBlank:
;Re-blank mouse if a new window has been activated.
move.l MBlankWindow(a1),d0
beq .Loop
cmp.l ib_ActiveWindow(a6),d0
beq .EndMBW
lea BlankMouse(pc),a2
bsr DoFunc
.EndMBW:
.Loop: cmp.b #IECLASS_TIMER,ie_Class(a0)
beq .Timer
cmp.b #IECLASS_RAWKEY,ie_Class(a0)
bne .NotKey
tst.b ie_Code+1(a0)
bmi .Next ;ignore up key codes
bsr RestoreScreen
;Handle immediate blank feature
tst.l ImmBlankOption(a1)
beq .SkipImmBlank
;Check for lamiga+ramiga
cmp.b #IEQUALIFIER_LCOMMAND+IEQUALIFIER_RCOMMAND,ie_Qualifier+1(a0)
bne .SkipImmBlank
bsr BlankScreen
.SkipImmBlank:
;Perform SunKey
tst.l SunKeyOption(a1)
beq .SkipSKey
lea ActivateWindow(pc),a2
bsr DoFunc
.SkipSKey:
;Do Northgate keyboard mapping.
tst.l NorthGateOption(a1)
beq .SkipNorthgate
lea NorthgateTable(pc),a2
move.w ie_Code(a0),d0
bclr #7,d0
.NorthgateLoop:
move.b (a2),d1
beq .EndNorthgate
addq.l #3,a2
cmp.b d0,d1
bne .NorthgateLoop
and.w #$80,ie_Code(a0)
move.b -2(a2),d0
or.b d0,ie_Code+1(a0)
move.b -1(a2),d0
bmi .EndNorthgate
bset d0,ie_Qualifier+1(a0)
.EndNorthgate:
.SkipNorthgate:
btst #IEQUALIFIERB_LCOMMAND,ie_Qualifier+1(a0)
bne .DoLAmiga
;Blank mouse pointer
tst.l MBlankOption(a1)
beq .NoMBlank
lea BlankMouse(pc),a2
bsr DoFunc
.NoMBlank:
bra .Next
.DoLAmiga:
tst.l CmdOption(a1)
beq .Next
cmp.w #$45,ie_Code(a0) ;ESC?
bne .Next
clr.b ie_Class(a0)
lea PopCLI(pc),a2
bsr DoFunc
bra .End
.NotKey: bsr RestoreScreen
.Timer: move.w ib_MouseX(a6),d0
move.w ib_MouseY(a6),d1
cmp.b #IECLASS_RAWMOUSE,ie_Class(a0)
beq .DoMouse
cmp.w CurrentX(a1),d0
bne .DoMouse
cmp.w CurrentY(a1),d1
beq .Next
.DoMouse:
move.w d0,CurrentX(a1)
move.w d1,CurrentY(a1)
tst.l MBlankOption(a1)
beq .NoRestore
move.l ie_TimeStamp(a0),MouseTime(a1)
lea RestoreMouse(pc),a2
bsr DoFunc
.NoRestore:
;Perform SunMouse
tst.l SunMouseOption(a1)
beq .SkipSunMouse
move.w ie_Qualifier(a0),d0
and.w #IEQUALIFIER_LEFTBUTTON+IEQUALIFIER_RBUTTON+IEQUALIFIER_MIDBUTTON,d0
bne .SkipSunMouse
cmp.w #IECODE_LBUTTON+IECODE_UP_PREFIX,ie_Code(a0)
beq .SkipSunMouse
move.l SunMouseDelayOption(a1),a2
move.l a2,d0
beq .SkipLoad
move.l (a2),d0
.SkipLoad:
addq.l #1,d0
move.l d0,SunMouseDelay(a1)
.SkipSunMouse:
;Perform click-to-back.
cmp.w #IECODE_RBUTTON,ie_Code(a0)
bne .NoCTB
move.w ie_Qualifier(a0),d0
btst #IEQUALIFIERB_LEFTBUTTON,d0
beq .DoSunRMB
tst.l STBOption(a1)
bne .DoCTB
tst.l CTBOption(a1)
beq .NoCTB
.DoCTB: lea CTB(pc),a2
bsr DoFunc
clr.b ie_Class(a0)
bra .Next
.DoSunRMB:
;Perform SunRMB
tst.l SunRMBOption(a1)
beq .SkipSunRMB
lea ActivateWindow(pc),a2
bsr DoFunc
.SkipSunRMB:
.NoCTB:
;Perform click-to-front.
tst.l CTFOption(a1)
beq .NoCTF
cmp.w #IECODE_LBUTTON,ie_Code(a0)
bne .NoCTF
btst #IEQUALIFIERB_LCOMMAND,ie_Qualifier+1(a0)
bne .NoCTF ;to avoid interferring with Snap
lea CTF(pc),a2
bsr DoFunc
.NoCTF:
;Perform acceleration.
tst.l AccelOption(a1)
beq .Next
move.l ThreshOption(a1),d0
beq .T1
move.l d0,a2
move.l (a2),d0
.T1: move.w ie_X(a0),d1
bpl .PosX
neg.w d1
.PosX: cmp.w d0,d1
bls .SkipX ;below threshold
move.l AccelOption(a1),a2
move.l (a2),d1
muls.w ie_X(a0),d1
tst.w ie_X(a0)
bpl .SubDampX
add.w DampingConstant(a1),d1
bra .DampX
.SubDampX:
sub.w DampingConstant(a1),d1
.DampX: move.w d1,ie_X(a0)
.SkipX: move.w ie_Y(a0),d1
bpl .PosY
neg.w d1
.PosY: cmp.w d0,d1
bls .EndAccel
move.l AccelOption(a1),a2
move.l (a2),d1
muls.w ie_Y(a0),d1
tst.w ie_Y(a0)
bpl .SubDampY
add.w DampingConstant(a1),d1
bra .DampY
.SubDampY:
sub.w DampingConstant(a1),d1
.DampY: move.w d1,ie_Y(a0)
.EndAccel:
.Next: move.l a0,d1
move.l (a0),d0
move.l d0,a0
bne .Loop
;Check for time-outs (mouse and screen blanking)
move.l d1,a0
tst.l MBlankOption(a1)
beq .NoMTime
tst.l MBlankWindow(a1)
bne .NoMTime
move.l MBlankOption(a1),a0
move.l (a0),d0 ;get value in seconds
move.l d1,a0
move.l ie_TimeStamp(a0),d1
tst.l MouseTime(a1)
beq .InitMBlank
sub.l MouseTime(a1),d1
cmp.l d0,d1 ;TimePassed ? UserSetting
blo .NoMTime
lea BlankMouse(pc),a2
bsr DoFunc
.NoMTime:
tst.l SBlankOption(a1)
beq .End
btst #STB_SBlanked,Status(a1)
bne .End
push a0
move.l SBlankOption(a1),a0
move.l (a0),d0 ;get value in seconds
pop a0
move.l ie_TimeStamp(a0),d1
tst.l ScreenTime(a1)
beq .InitSBlank
sub.l ScreenTime(a1),d1
cmp.l d0,d1 ;TimePassed ? UserSetting
blo .End
bsr BlankScreen
.End: bsr FreeIBase
move.l (sp)+,d0
movem.l (sp)+,d2/a2/a6
rts
.InitMBlank:
move.l ie_TimeStamp(a0),MouseTime(a1)
bra .NoMTime
.InitSBlank:
move.l ie_TimeStamp(a0),ScreenTime(a1)
bra .End
;Enter with global pointer in A1.
;d0, d1, a0, a1, a5, and a6 are scratch.
;Must always end with a "moveq #0,d0" to set the Z flag.
VBlankRoutine:
tst.l SunMouseDelay(a1)
beq .End
subq.l #1,SunMouseDelay(a1)
bne .End
move.l a2,-(sp)
lea ActivateWindow(pc),a2
bsr DoFunc
move.l (sp)+,a2
.End: moveq #0,d0
rts
GlobalPtr:
dc.l 0
NorthgateTable:
;Assign PageUp/PageDown/Home/End to shift-cursor sequences
dc.b $6b,$4f,IEQUALIFIERB_LSHIFT
dc.b $6c,$4e,IEQUALIFIERB_LSHIFT
dc.b $6d,$4c,IEQUALIFIERB_LSHIFT
dc.b $6e,$4d,IEQUALIFIERB_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 'QMouse process',0
InputName:
dc.b 'input.device',0
TrackName:
dc.b 'trackdisk.device',0
even
;*************************** Debugging stuff *************************
IFNE INFO_LEVEL
KPutFmt: movem.l a2/a6,-(sp)
move.l 4,a6
lea KPutChar(pc),a2
SYS RawDoFmt
movem.l (sp)+,a2/a6
rts
KPutChar:
;Serial
comment |
move.l a6,-(sp)
move.l 4,a6
SYS RawPutChar
move.l (sp)+,a6
rts
|
;Printer
comment |
move.b #$ff,$bfe301
.Print: btst #0,$bfd000
bne .Print
move.b d0,$bfe101
rts
|
;Memory
movem.l a0-a1,-(sp)
lea MemPtr(pc),a1
move.l (a1),a0
move.b d0,(a0)+
move.l a0,(a1)
movem.l (sp)+,a0-a1
rts
MemPtr: dc.l $300000
ENDC
EndAllocCode: ;end of code copied into allocated memory
;***********************************************************************
NewProcTags:
dc.l NP_Entry
EntryPoint:
dc.l 0
dc.l NP_Name
ProcNamePtr:
dc.l 0
dc.l NP_Cli,-1
dc.l NP_Priority,TaskPriority
dc.l 0 ;end of tags
Template: dc.b 'M=MBLANK/K/N,'
dc.b 'S=SBLANK/K/N,'
dc.b 'N=NOFLICKER/S,'
dc.b 'CMD/K,'
dc.b 'A=ACCELERATION/K/N,'
dc.b 'T=THRESHOLD/K/N,'
dc.b 'CTB=CLICKTOBACK/S,'
dc.b 'STB=SCREENTOBACK/S,'
dc.b 'CTF=CLICKTOFRONT/K/N,'
dc.b 'SUNMOUSE/S,'
dc.b 'SUNKEY/S,'
dc.b 'NORTHGATE/S,'
dc.b 'NOBEEP/S,'
dc.b 'NOCLICK/K/N,'
dc.b 'VERIFY/S,'
dc.b 'NOVERIFY/S,'
dc.b 'STAR/S,'
dc.b 'NoWBenchToFront/S,'
dc.b 'PUBCHANGE/S,'
dc.b 'SunMouseDelay/K/N,'
dc.b 'ImmBlank/S,'
dc.b 'NoActivate/S,'
dc.b 'SunRMB/S,'
dc.b 'QUIT/S',0
IntName: dc.b 'intuition.library',0
GraphName:
dc.b 'graphics.library',0
DosName: dc.b 'dos.library',0
LayersName:
dc.b 'layers.library',0
UtilityName:
dc.b 'utility.library',0
BadArgs: dc.b 'Bad arguments.',$a,0
dc.b '$VER: QMouse 2.90 (4.1.94)',$a,0
;The ordering here is special: data registers first, then address
;registers, so that MOVEM may be used to save/restore the data.
STRUCTURE pt,0
LONG pt_Height
LONG pt_Width
LONG pt_XOffset
LONG pt_YOffset
LONG pt_Window
LONG pt_Pointer
BYTE TagVersion ;special boolean indicator
BYTE pt_pad
LABEL pt_Sizeof
ResidentCodeSize equ EndAllocCode-StartAllocCode
STRUCTURE Data,0
WORD Nothing ;to make zero special
LABEL Sigs
LONG QuitSig
LONG FuncSig
LABEL EndSigs
LABEL Semaphores
STRUCT MySemaphore,SS_SIZE
STRUCT CloseWindowSemaphore,SS_SIZE
STRUCT CloseScreenSemaphore,SS_SIZE
STRUCT CloseWBSemaphore,SS_SIZE
LABEL EndSemaphores
LONG Task
LONG InputMsgPort
LONG InputIORequest
STRUCT InputInterrupt,IS_SIZE
LONG IntBase
LONG GraphBase
LONG LayersBase
LONG _UtilityBase
STRUCT ScreenList,SCREENLISTSIZE*8
STRUCT PointerList,POINTERLISTSIZE*pt_Sizeof
STRUCT TaskQueue,MAXQUEUE*4+4
LONG OldCloseScreen
LONG OldCloseWorkBench
LONG OldCloseWindow
LONG OldSetPointer
LONG OldSetWindowPointerA
LONG OldClearPointer
LONG OldDisplayBeep
LONG OldOpenWindowTagList
LONG DosBase
LONG ArgPtr
STRUCT ResidentCode,ResidentCodeSize
LONG MouseTime ;timeout for mouse blanking
LONG ScreenTime ;for screen blanking
LONG BlankScreenPtr
LONG BlankScreenWindowPtr
LONG MBlankWindow
WORD DampingConstant
LONG ClickWindow
STRUCT ClickTime,TV_SIZE
LONG ClickCount
LONG Path
LONG ChipData
LONG RealBackground
LONG OriginalCopInit
WORD CurrentX
WORD CurrentY
LONG WaitLineAddress
LONG CurrentTopScreen
LONG CurrentActiveScreen
LONG CurrentActiveWindow
LONG SunMouseDelay
STRUCT VBlankServer,IS_SIZE
LONG IBaseLock
LABEL Options
LONG MBlankOption
LONG SBlankOption
LONG FlickerOption
LONG CmdOption
LONG AccelOption
LONG ThreshOption
LONG CTBOption
LONG STBOption
LONG CTFOption
LONG SunMouseOption
LONG SunKeyOption
LONG NorthGateOption
LONG BeepOption
LONG NoClickOption
LONG VerifyOption
LONG NoVerifyOption
LONG StarOption
LONG NoWBenchToFrontOption
LONG PubChangeOption
LONG SunMouseDelayOption
LONG ImmBlankOption
LONG NoActivateOption
LONG SunRMBOption
LONG QuitOption
BYTE HandlerInstalled
BYTE Status ;various status bits (defined below)
LABEL Data_Sizeof
;Bit definitions for Status
BITDEF ST,SBlanked,0
BITDEF ST,IntInstalled,1
NumSigs equ (EndSigs-Sigs)/4
NumSemaphores equ (EndSemaphores-Semaphores)/SS_SIZE
STRUCTURE CData,0
STRUCT ZeroMouse,12
STRUCT Copper,MaxCopperSize+4*4
LABEL CData_Sizeof
end