[comp.sys.mac.programmer] How to Patch

holland@mips.csc.ti.com (Fred Hollander) (11/04/88)

I would like to patch the Alert trap and I've been having a hard time
finding documentation that spells out the procedure on patches.  I understand
the basic idea: save the existing trap address, set the trap address to point
to your patch, call the old trap, return.  What's missing is how to install
the patch in the first place.  I don't know anything about a PTCH resource.
How do I install the code permanently in the System heap?

Here's a first pass at trying to update the trap dispatch table.  The trap
address for SysBeep seems to have changed while in LSC (by re-executing
GetTrapAddress), but after exiting, the trap address reverts back to the
original address.

#define	trapSysBeep		0xA9C8

long	oldTrapAddress;

newBeep (ignore)
	int	ignore;
	{
		asm{
			move.l	oldTrapAddress,A1
			jsr	(A1)
			rts
		}
	}

main () {
	oldTrapAddress = GetTrapAddress (trapSysBeep);
	SetTrapAddress (newBeep, trapSysBeep);
}

If someone could send me an example, preferrably in LSC, I'd sure appreciate
it.

Thanks,

Fred Hollander
Computer Science Center
Texas Instruments, Inc.
holland%ti-csl@csnet-rela

The above statements are my own and not representative of Texas Instruments.

bob@eecs.nwu.edu (Bob Hablutzel) (11/05/88)

You don't want to mess with a PTCH resource. Rather, you want to
write an INIT file, put it in the system folder, and let the system
execute the INIT at startup time. 

An INIT is basically a resource containing code. It takes no parameters,
and the entry point is at the start of the resource. I find it's easiest
to write these beasts in Assembler, but there is usually some means of
writing them in high level languages.

Read the start manager chapter of IM V. I think everything is covered in 
that chapter.

Bob Hablutzel	BOB@NUACC.ACNS.NWU.EDU

ech@poseidon.ATT.COM (Edward C Horvath) (11/07/88)

From article <10050042@eecs.nwu.edu>, by bob@eecs.nwu.edu (Bob Hablutzel):
> You don't want to mess with a PTCH resource...

No, he wants to know how to OVERRIDE or REPLACE a system trap, right?

The straight answer is:
	- Use GetTrapAddress to get the address of the trap handler.
	- Use SetTrapAddress to replace that one with your own.

Note that your own trap handler has to be in a locked-down chunk of code in
order for that to be viable.  There are a couple of choices for INIT code:

- allocate a block (NewPtr) in the System heap.  Install your code there.
- reduce the value in BufPtr (the effective top of memory) by the size of
the permanent block you want, and put your stuff there.  There's no simple
way to release that memory later, so you own it 'til reboot.

=Ned Horvath=

holland@mips.csc.ti.com (Fred Hollander) (11/09/88)

Thanks to those who responded to my request for help.  I finally got
something to work.  Here it is in case anybody else would like to use it.
Build a code resource, type INIT, with the System and Locked attributes.
There's a bit of a kludge in there because, unless I'm mistaken, the
standard header provided by LightSpeed C trashes A0 beyond recovery.  I
modified the header (in ResEdit) by putting an extra instruction to push
registers A0-A2 on the stack.  An alternative would be to store the globals'
base address and skip the header or write a custom header.  Does anyone have
the standard header?  What else does it do besides put the entry point into
A0?

Fred Hollander
Computer Science Center
Texas Instruments, Inc.
holland%ti-csl@csnet-rela

The above statements are my own and not representative of Texas Instruments.
The code below is my own and not representative of Texas Instruments.

#include <SetUpA4.h>

#define	trapSysBeep		0xA9C8

long	oldTrapAddress;
Handle	trapHandle;
char	installed = false;

void main () {
	/*  
	Manually put this (48E7 00E0) in the header at 0x000C
	so that it is called before AO is trashed!
	Change 0x0000 from 600E to 600A to point to this move.
	(May be easier to write a custom header.)
	asm{
		movem.l		A0-A2,-(A7)
	}
	*/
	RememberA0 ();
	SetUpA4 ();
	if (installed) {
		/* Put your stuff here */
		asm{
			move.l		oldTrapAddress,A3
		}
		RestoreA4 ();
		asm{
			movem.l		(A7)+,A0-A2
		}
		asm{
			jmp		(A3)
		}
	} else {
		asm{
			move.l		A4,A0
			_RecoverHandle
			move.l		A0,trapHandle
		}
		DetachResource (trapHandle);
		HLock (trapHandle);
		oldTrapAddress = GetTrapAddress (trapSysBeep);
		SetTrapAddress ((long) *trapHandle, trapSysBeep);
		installed = true;
		RestoreA4 ();
		asm{
			movem.l		(A7)+,A0-A2
		}
	}
}