home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Club Amiga de Montreal - CAM
/
CAM_CD_1.iso
/
files
/
500.lha
/
NoCare_v1.5
/
NoCare.asm
< prev
next >
Wrap
Assembly Source File
|
1991-04-08
|
12KB
|
485 lines
;-----------------------------------------------------------------------------
;
; Program : NoCare.asm V1.5
; Author : Raymond Hoving, The Orega Programming Group Holland
; Creation Date : Wed Jan 16 19:28:28 1991
; Purpose : A utility to speed up the workbench window environment.
; Usage : NoCare - Starts/stops the program from a CLI/Shell.
;
; See copyright notes in file called 'NoCare.doc'.
; Bug reports or comments to:
;
; The Orega Programming Group Holland,
; P.o.box 499, Apothekersdijk 24,
; 2280 AL Rijswijk, 2312 DD Leiden,
; The Netherlands. The Netherlands.
; Phone .. - (0)71 - 14 49 71
;
; or UUCP: breemen@rulcvx.LeidenUniv.nl (shared account).
;
;-----------------------------------------------------------------------------
OPENLIB macro ; \1 library name.
data ; \2 address of failure handling code.
\1name dc.b '\1.library',0 Use 0 for \1fails.
even ; \3 Optional version number.
\1base ds.l 1 ; (Default value is 33)
code ; Registers affected d0,a1,a6.
lea.l \1name,a1
ifne NARG-3
move.l #33,d0
endc
ifeq NARG-3
move.l #\3,d0
endc
CALL exec,OpenLibrary
move.l d0,\1base
ifc '\2','0'
beq \1fails
endc
ifnc '\2','0'
beq \2
endc
endm
CLOSELIB macro ; \1 library name.
move.l \1base,a1 ; Registers affected a1,a6.
CALL exec,CloseLibrary
endm
CALL macro ; \1 library name.
ifnc '\1','exec' ; \2 function name.
move.l \1base,a6 ; Registers affected a6.
endc
ifc '\1','exec'
move.l _SysBase,a6
endc
jsr _LVO\2(a6)
endm
CALLR macro ; \1 function name.
jsr _LVO\1(a6) ; No registers affected.
endm
STANDARDOUTPUT macro ; Init of stdout, used by PRINT etc.
data
stdout ds.l 1
code
CALL dos,Output
move.l d0,stdout
endm
PRINT macro ; Prints string at location \1
move.l stdout,d1 ; with lenght \2. No automatic
move.l #\1,d2 ; linefeed.
move.l #\2,d3
CALL dos,Write
endm
_LVOOpenLibrary equ -552 ; Library vector offsets.
_LVOCloseLibrary equ -414 ; No need to link with amiga.lib.
_LVOOutput equ -60
_LVOWrite equ -48
_LVOAllocSignal equ -330
_LVOFreeSignal equ -336
_LVOFindTask equ -294
_LVOFindPort equ -390
_LVOAddPort equ -354
_LVORemPort equ -360
_LVOAllocEntry equ -222
_LVOWaitPort equ -384
_LVOGetMsg equ -372
_LVOPutMsg equ -366
_LVOReplyMsg equ -378
_LVOSetFunction equ -420
_LVOForbid equ -132
_LVOPermit equ -138
_LVOCopyMem equ -624
_LVOAddTail equ -246
_LVOAddTask equ -282
_LVORemTask equ -288
_LVOOpenWindow equ -204
_SysBase equ $4
include exec/exec.i
include intuition/intuition.i
include intuition/screens.i
REFRESHBIT0 equ $06
REFRESHBIT1 equ $07 ; Bits in the nw_Flags field.
STACKSIZE equ 200 ; Stack size for the NoCare task.
MN_CONTENTS equ MN_SIZE
REPLY equ $0
FAILURE equ $1
SUCCESS equ $2
REMOVE equ $3 ; Inter-task communication defenitions.
code
; Open dos.library and print message.
OPENLIB dos,0
STANDARDOUTPUT
PRINT mess1,mess2-mess1
; Create a message port for communication with the NoCare task:
move.l #-1,d0
CALL exec,AllocSignal
move.b d0,signal1
bmi signal1fails ; Allocate a signal.
sub.l a1,a1
CALLR FindTask
lea.l port1,a1
move.l d0,MP_SIGTASK(a1) ; Link this task into messageport.
move.b signal1,MP_SIGBIT(a1) ; Link allocated signal into port.
CALLR AddPort ; Make the port a public one.
; Is NoCare active already?
CALLR Forbid
lea.l port2name,a1 ; Try to find NoCare2.Orega port.
CALLR FindPort
move.l d0,d6
CALLR Permit
tst.l d6
bne sendremovemessage
; The NoCare2.Orega port has not been found, so start the NoCare task:
; First allocate memory for the task structure, the stack and a safe
; place for the PC-relative code of the NoCare task.
lea.l memlist1,a0
CALLR AllocEntry
bclr.l #31,d0
bne allocerror ; Not enough memory!
move.l d0,a5 ; Remember address in a5.
; Then copy the PC-relative taskcode to the safe place:
move.l LN_SIZE+10(a5),a1 ; Get pointer to allocated memory.
lea.l codestart,a0
move.l #codeend-codestart,d0
CALLR CopyMem
; Then create the new task (has no name yet):
move.l LN_SIZE+2(a5),a0 ; Get pointer to allocated memory.
; Link stack, task structure and code area into task's memlist:
lea.l TC_MEMENTRY(a0),a0 ; Get pointer to task's memlist.
move.b #NT_MEMORY,LN_TYPE(a0)
move.l a0,(a0)
addq.l #LH_TAIL,(a0)
clr.l LH_TAIL(a0) ; Initialise list structure.
move.l a0,(LH_TAIL+LN_PRED)(a0)
move.l a5,a1
CALLR AddTail ; Add node to memlist.
move.l LN_SIZE+2(a5),d0
move.l d0,a1
add.l #TC_SIZE,d0
move.l d0,TC_SPLOWER(a1) ; Lower stack boundary,
add.l #STACKSIZE,d0
move.l d0,TC_SPUPPER(a1) ; Upper stack boundary.
move.l d0,TC_SPREG(a1) ; Initial stack pointer.
move.b #NT_TASK,LN_TYPE(a1) ; Node type.
move.l LN_SIZE+10(a5),a2 ; Initial PC of NoCare task.
sub.l a3,a3
CALLR AddTask ; Lets's go!
RemTask
; The NoCare task has been launched, now wait for the startup message:
getmsgloop1
lea.l port1,a0
CALLR WaitPort ; Wait for a message.
lea.l port1,a0
CALLR GetMsg ; Get the new message.
move.l d0,a1
move.w MN_CONTENTS(a1),d6 ; Save the important field.
move.w #REPLY,MN_CONTENTS(a1) ; Mark as a replied message.
CALLR ReplyMsg ; Quickly reply message.
; Examine the startup message now:
cmp.w #FAILURE,d6
beq.s installfailed
cmp.w #SUCCESS,d6
bne.s getmsgloop1 ; Should never execute this.
PRINT mess2,mess3-mess2 ; 'Installed.'
bra ex1
installfailed
PRINT mess4,mess5-mess4 ; 'Could not install.'
bra ex1
; Send a message to the messageport of the NoCare task.
; This informs the NoCare task to remove the OpenWindow patch.
; The address of the messageport is in d6:
sendremovemessage
lea.l message1,a1
move.w #REMOVE,MN_CONTENTS(a1)
move.l d6,a0 ; Destination port.
CALLR PutMsg
getmsgloop2
lea.l port1,a0
CALLR WaitPort ; Wait for reply.
lea.l port1,a0
CALLR GetMsg
move.l d0,a0
move.w MN_CONTENTS(a0),d0
; We asked the NoCare task to remove itself (and of course the
; OpenWindow patch). Examine the reply of the NoCare task:
cmp.w #FAILURE,d0
beq.s remerror
cmp.w #SUCCESS,d0
bne.s getmsgloop2 ; Should never execute this.
PRINT mess3,mess4-mess3 ; 'Removed.'
bra.s ex1
remerror
PRINT mess5,mess6-mess5 ; 'Could not remove.'
bra.s ex1
; Error handling code:
signal1fails
PRINT mess6,mess7-mess6
bra.s ex0
allocerror
PRINT mess6,mess7-mess6
; Cleanup code follows:
ex1 lea.l port1,a1
CALL exec,RemPort
clr.l d0
move.b signal1,d0 ; Free signal.
CALLR FreeSignal
ex0 CLOSELIB dos
dosfails
rts
data
message1 dc.l 0,0 ; ln_succ, ln_pred
dc.b NT_MESSAGE,0 ; ln_type, ln_pri
dc.l 0 ; ln_name
dc.l port1 ; mn_replyport
dc.w MN_SIZE+2 ; mn_length
dc.w 0 ; mn_contents
port1 dc.l 0,0 ; ln_succ, ln_pred
dc.b NT_MSGPORT,1 ; ln_type, ln_pri
dc.l port1name ; ln_name
dc.b PA_SIGNAL,0 ; mp_flags, mp_sigbit
dc.l 0 ; mp_sigtask
dc.l 0,0,0 ; lh_head, lh_tail, lh_tailpred
dc.b NT_MESSAGE,0 ; lh_type, lh_pad
memlist1 dc.l 0,0 ; ln_succ, ln_pred
dc.b NT_MEMORY,0 ; ln_type, ln_pri
dc.l 0 ; ln_name
dc.w 2 ; Numer of entries.
dc.l MEMF_PUBLIC!MEMF_CLEAR
dc.l STACKSIZE+TC_SIZE
dc.l MEMF_PUBLIC
dc.l codeend-codestart
signal1 ds.l 1
port1name dc.b 'NoCare1.Orega',0
port2name dc.b 'NoCare2.Orega',0
mess1 dc.b $1b,'[33mNoCare V1.5',$1b,'[0m by Raymond Hoving,'
dc.b ' THE OREGA PROGRAMMING GROUP HOLLAND.',$a
mess2 dc.b 'OpenWindow() patch installed.',$a
mess3 dc.b 'OpenWindow() patch removed.',$a
mess4 dc.b 'ERROR: Could not install.',$a
mess5 dc.b 'ERROR: Could not remove.',$a
mess6 dc.b 'ERROR: Out of memory/signals',$a
mess7
;-----------------------------------------------------------------------------
; Now follows the code of the NoCare task. This code is PC-relative.
; First we give this task a name:
code
codestart
sub.l a1,a1
CALL exec,FindTask
move.l d0,a0
lea.l taskname(PC),a1
move.l a1,LN_NAME(a0)
; Open intuition.library:
lea.l intuitionname(PC),a1
clr.l d0
CALLR OpenLibrary
lea.l intuitionbase(PC),a2
move.l d0,(a2)
; beq.s intuitionfails ; Any version will do.
; Then patch the OpenWindow() function:
move.l d0,a1
move.w #_LVOOpenWindow,a0
lea.l newopenwindow(PC),a2
move.l a2,d0
CALLR SetFunction
lea.l oldopenwindow(PC),a2
move.l d0,(a2)
; Create a message port (called NoCare2.Orega)
move.l #-1,d0
CALLR AllocSignal
; bmi signal2fails ; It's my task!
lea.l signal2(PC),a2
move.b d0,(a2)
sub.l a1,a1
CALLR FindTask
lea.l port2(PC),a1
move.l d0,MP_SIGTASK(a1)
lea.l port2name2(PC),a0
move.l a0,LN_NAME(a1)
move.b signal2(PC),MP_SIGBIT(a1)
CALLR AddPort ; Add port to system.
; Now send a message to our parent task, that NoCare is installed
; without problems:
CALLR Forbid
lea.l port1name2(PC),a1 ; Try to find NoCare1.Orega port.
CALLR FindPort
move.l d0,d6 ; Remember port in d6.
CALLR Permit
tst.l d6
; beq port1gone ; Impossible situation!
lea.l port2(PC),a0
lea.l message2(PC),a1
move.l a0,MN_REPLYPORT(a1)
move.w #SUCCESS,MN_CONTENTS(a1)
move.l d6,a0 ; Destination port.
CALLR PutMsg
; Then wait for the REPLY message or the REMOVE message:
getmsgloop3
lea.l port2(PC),a0
CALLR WaitPort ; Wait for message.
lea.l port2(PC),a0
CALLR GetMsg
move.l d0,a0
cmp.w #REMOVE,MN_CONTENTS(a0)
bne.s getmsgloop3 ; It's the REPLY message.
move.l d0,a5 ; Remember this message.
; So the user wants to terminate NoCare.
; First test if someone else patched our patch.
CALLR Forbid
move.l intuitionbase(PC),a3
move.l _LVOOpenWindow+2(a3),a3 ; Get OpenWindow vector.
lea.l newopenwindow(PC),a4
cmp.l a3,a4
bne.s removeerror
; Now we restore the old OpenWindow vector:
move.l oldopenwindow(PC),d0 ; Pointer to original code.
move.l intuitionbase(PC),a1
move.w #_LVOOpenWindow,a0
CALLR SetFunction
CALLR Permit
; Then we remove the messageport and free the signal bit:
lea.l port2(PC),a1
CALLR RemPort
clr.l d0
move.b signal2(PC),d0
CALLR FreeSignal ; Just to be nice.
; Reply the REMOVE message:
move.l a5,a1 ; Pointer to the REMOVE message.
move.w #SUCCESS,MN_CONTENTS(a1)
CALLR ReplyMsg
; Close intuition.library:
move.l intuitionbase(PC),a1
CALLR CloseLibrary
; Then call exec's standard task finalizer. The task structure,
; it's stack and the safeplace-area will be freed.
sub.l a1,a1
CALLR RemTask ; End of NoCare task.
;-----------------------------------------------------------------------------
; When NoCare could not be removed, we reply with a failure type message.
removeerror
CALLR Permit
move.l a5,a1
move.w #FAILURE,MN_CONTENTS(a1)
CALLR ReplyMsg
bra getmsgloop3 ; Wait for another try...
;-----------------------------------------------------------------------------
; As OpenWindow() is called, then a0 points to a NewWindow structure.
; We patch a bit in the nw_Flags field and than jump to the original
; OpenWindow() code.
newopenwindow
cmp.w #WBENCHSCREEN,nw_Type(a0)
bne.s dontchange
move.l nw_Flags(a0),d0
bclr #REFRESHBIT0,d0 ; We don't want SIMPLE_REFRESH ones.
move.l d0,nw_Flags(a0)
dontchange
move.l oldopenwindow(PC),a1
jmp (a1) ; Jump to original code.
;-----------------------------------------------------------------------------
message2 dc.l 0,0 ; ln_succ, ln_pred
dc.b NT_MESSAGE,0 ; ln_type, ln_pri
dc.l 0 ; ln_name
dc.l 0 ; mn_replyport
dc.w MN_SIZE+2 ; mn_length
dc.w 0 ; mn_contents
port2 dc.l 0,0 ; ln_succ, ln_pred
dc.b NT_MSGPORT,1 ; ln_type, ln_pri
dc.l 0 ; ln_name
dc.b PA_SIGNAL,0 ; mp_flags, mp_sigbit
dc.l 0 ; mp_sigtask
dc.l 0,0,0 ; lh_head, lh_tail, lh_tailpred
dc.b NT_MESSAGE,0 ; lh_type, lh_pad
oldopenwindow ds.l 1
signal2 ds.l 1
intuitionbase ds.l 1
taskname dc.b 'NoCareTask.Orega',0
port1name2 dc.b 'NoCare1.Orega',0
port2name2 dc.b 'NoCare2.Orega',0
intuitionname dc.b 'intuition.library',0
codeend
end
;-----------------------------------------------------------------------------