;----------------------------------------------------------------------------- ; ; 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 ;-----------------------------------------------------------------------------