[comp.sys.amiga.tech] SetFunction

pl@kaarne.tut.fi (Pertti Lehtinen) (04/03/89)

From article <6462@cbmvax.UUCP>, by eric@cbmvax.UUCP (Eric Cotton):
> 
> SetFunction does indeed return a pointer to the old function.
> 
> 	oldFunc = SetFunction(library, funcOffset, funcEntry)

	That makes things interesting.

	How does find out the address of original function?

	Does it copy old stub somewhere and return address to that?

	Or does it simply use stub as normal library stub (jmp xxx),
	and return xxx.  In this case it isn't surprising that
	it doesn't work with DOS-library.

	Exec manual don't say anything about return value,
	so does it just happen
	under certain circumstances or is it on purpose?

					Pertti Lehtinen
					pl@tut.fi

pl@tut.fi				! -------------------------------- !
Pertti Lehtinen				!  Alone at the edge of the world  !
Tampere University of Technology	! -------------------------------- !
Software Systems Laboratory

ahinds@hvrunix.UUCP (Alexander Hinds) (04/03/89)

	Can anybody tell me how to use SetFunction()?  I want to replace
DisplayBeep to point to my own code, because I hate screen flashing.  I'd
like it to play an IFF sample, or use SPEAK: instead.  I thought it would be
a cool hack.  Unfortunately, I seem to call SetFUnction incorrectly.  I did:

	SetFunction(IntuitionBase,(long)-60,&MyFunction);
I used -60 because it is DisplayBeep() offeset.(I think).  Any help would
be appreciated, and a personal response would be much better than one posted.

Sincerely,,
	Alexander HInds

USENET:ahinds@hvrford

scott@applix.UUCP (Scott Evernden) (04/04/89)

In article <518@hvrunix.UUCP> ahinds@hvrunix.UUCP (Alexander Hinds) writes:
>
>	Can anybody tell me how to use SetFunction()?  ...
>
>	SetFunction(IntuitionBase,(long)-60,&MyFunction);
>I used -60 because it is DisplayBeep() offeset.(I think).

-60 HEXADECIMAL  HEX HEX


hex

x

-scott

deven@pawl.rpi.edu (Deven Corzine) (04/05/89)

In article <518@hvrunix.UUCP> ahinds@hvrunix.UUCP (Alexander Hinds) writes:
[SetFunctioning DisplayBeep...]
	   SetFunction(IntuitionBase,(long)-60,&MyFunction);

You may be causing problems using "&MyFunction"...  If you have a
function MyFunction(), "MyFunction" is a _pointer_ to that function.
"main" is a pointer to your main() function.  Someone else mentioned
the offset for DisplayBeep being -60 HEX.  (I have NOT looked this
up.)  So, it seems your function call should be:

     OldDisplayBeep=SetFunction(IntuitionBase,0x60L,MyFunction);

Deven
--
------- shadow@pawl.rpi.edu ------- Deven Thomas Corzine ---------------------
Cogito  shadow@acm.rpi.edu          2346 15th Street            Pi-Rho America
ergo    userfxb6@rpitsmts.bitnet    Troy, NY 12180-2306         (518) 272-5847
sum...     In the immortal words of Socrates:  "I drank what?"     ...I think.

kodiak@amiga.UUCP (Robert R. Burns) (04/06/89)

In article <518@hvrunix.UUCP> ahinds@hvrunix.UUCP (Alexander Hinds) writes:
>
>	Can anybody tell me how to use SetFunction()?  ...
>
>	SetFunction(IntuitionBase,(long)-60,&MyFunction);
>I used -60 because it is DisplayBeep() offeset.(I think).

er, why mess with numbers?

    extern int LVODisplayBeep;

    SetFunction(IntuitionBase, &LVODisplayBeep, &MyFunction);

and link with amiga.lib
-- 
Bob Burns, amiga!kodiak                    _
| /_  _|. _ |      Commodore __           |_) _ |_  _ )'
|<(_)(_)|(_\|<      /\ |  ||| _` /\       |_)(_\| )(_\ |
| \ Software    ___/..\|\/|||__|/..\___            Faith

ewhac@well.UUCP (Leo L. Schwab) (04/07/89)

In article <3717@amiga.UUCP> kodiak@tooter.UUCP (Robert R. Burns) writes:
>In article <518@hvrunix.UUCP> ahinds@hvrunix.UUCP (Alexander Hinds) writes:
>>	SetFunction(IntuitionBase,(long)-60,&MyFunction);
>>I used -60 because it is DisplayBeep() offeset.(I think).
>
>er, why mess with numbers?
>
>    extern int LVODisplayBeep;
>
>    SetFunction(IntuitionBase, &LVODisplayBeep, &MyFunction);
>
	Is this the Officially Supported way to do this?  Since all the _LVO
offsets are declared as:

_LVOFooBarAndGrill	EQU	-3276

	I always wondered what a kosher way to reference those values from C
was.  The (untested) method I thought of was:

	extern int	LVOFooBarAndGrill[];
	SetFunction (LibraryBase, LVOFooBarAndGrill, ReplacementFunction);

	Are there other approaches?

_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
Leo L. Schwab -- The Guy in The Cape	INET: well!ewhac@ucbvax.Berkeley.EDU
 \_ -_		Recumbent Bikes:	UUCP: pacbell > !{well,unicom}!ewhac
O----^o	      The Only Way To Fly.	      hplabs / (pronounced "AE-wack")
"Work FOR?  I don't work FOR anybody!  I'm just having fun."  -- The Doctor

jimm@amiga.UUCP (Jim Mackraz) (04/22/89)

In article <DEVEN.89Apr5081411@daniel.pawl.rpi.edu> deven@pawl.rpi.edu (Deven Corzine) writes:
) So, it seems your function call should be:
)
)     OldDisplayBeep=SetFunction(IntuitionBase,0x60L,MyFunction);

I don't know if 0x60 is correct either, but I think you can use
LVODisplayBeep.  Just declare it as, hmm, what would that be?
Maybe int	LVODisplayBeep[];
or int LVODisplayBeep; then use &LVODisplayBeep.

Anyway, just suppose it's 0x60 ...

What I wanted to say was that the little function you replace DisplayBeep
with had better be reentrant, because people call this sucker a whole lot.
It would also be nice if it didn't run synchronously (which might lead you
to THINK it's reentrant), so that people don't have to wait for you to
be done beeping 100 times if they hold down a repeating key in a string
gadget or something.

I guess I just wanted to comment that beeping is harder than one (I) might
think.

	jimm
-- 
Jim Mackraz, I and I Computing	   	"He's hidden now, but you can see
{cbmvax,well,oliveb}!amiga!jimm          The bubbles where he breathes."
							- Shriekback
Opinions are my own.  Comments are not to be taken as Commodore official policy.

shadow@pawl.rpi.edu (Deven T. Corzine) (04/23/89)

In article <DEVEN.89Apr5081411@daniel.pawl.rpi.edu> I wrote:

>  OldDisplayBeep=SetFunction(IntuitionBase,0x60L,MyFunction);

In article <3767@amiga.UUCP> jimm@amiga.UUCP (Jim Mackraz) writes:
>I don't know if 0x60 is correct either, but I think you can use
>LVODisplayBeep.  Just declare it as, hmm, what would that be?
>Maybe int	LVODisplayBeep[];
>or int LVODisplayBeep; then use &LVODisplayBeep.

I wasn't sure either, and considered suggesting using LVODisplayBeep
to be sure, and for future compatibility -- just couldn't remember
offhand the proper semantics to do so.  Besides, then you gotta link
with amiga.lib, I think.  Icky.  :-)

>Anyway, just suppose it's 0x60 ...

I just looked it up; it is indeed 0x60.  (-0x0060, actually.)

>What I wanted to say was that the little function you replace DisplayBeep
>with had better be reentrant, because people call this sucker a whole lot.
>It would also be nice if it didn't run synchronously (which might lead you
>to THINK it's reentrant), so that people don't have to wait for you to
>be done beeping 100 times if they hold down a repeating key in a string
>gadget or something.

It should be reentrant and truncate the last beep if another one
starts, to prevent long-queued beep chains...

[I was going to mention that also, but I was being lazy...]

>I guess I just wanted to comment that beeping is harder than one (I) might
>think.

Indeed.

Deven
--
------- shadow@pawl.rpi.edu ------- Deven Thomas Corzine ---------------------
Cogito  shadow@acm.rpi.edu          2346 15th Street            Pi-Rho America
ergo    userfxb6@rpitsmts.bitnet    Troy, NY 12180-2306         (518) 272-5847
sum...     In the immortal words of Socrates:  "I drank what?"     ...I think.

dillon@POSTGRES.BERKELEY.EDU (Matt Dillon) (04/25/89)

:)     OldDisplayBeep=SetFunction(IntuitionBase,0x60L,MyFunction);
:
:I don't know if 0x60 is correct either, but I think you can use
:LVODisplayBeep.  Just declare it as, hmm, what would that be?

	Uh, aren't they supposed to be *negative* offsets?

						-Matt

jbickers@actrix.co.nz (John Bickers) (02/06/90)

In article <1472@jimi.cs.unlv.edu> maniac@hubert.cs.unlv.edu (Eric J. Schwertfeger) writes:
>   Is it possible to setfunction dos.library?  I have been told that the
> normal setfunction
> call willnot, but is it possible to do a work-around?

    Yes, the normal SetFunction() expects a library entry (6 bytes in the
    library table) to be:
                jmp     32-bit address
    So when you SetFunction a library vector it returns the top four bytes of
    the 6 as the function point it's supposed to return, and plugs in the
    4-byte pointer you provide. It also seems to re-write the jmp instruction
    code.

    This works fine for most libraries, but the DOS library doesn't have that
    type of entry. Instead of a jmp to a 32-bit address it has:
                moveq   nn,d0           ; nn is some value DOS understands
                bra.w   DOS routine
    The DOS routine is usually the same for all the different "vectors", and
    it must somehow work out from the value in d0 which DOS function you are
    calling (go BCPL! :).

    So to emulate SetFunction(), you have to write your own code that will
    replace the moveq,bra sequence with a 32-bit jump to your intercept code,
    and your intercept code must, at the end, move nn into d0 and then jmp to
    the destination of the original branch instruction.

    You can determine the value of nn and the destination of the original
    branch instruction by taking a debugger to the DOSBase vector. For
    example, a do-nothing program in Lattice C was enough for CodeProbe to
    pick up DOSBase from.

deven@rpi.edu (Deven T. Corzine) (02/08/90)

In article <1472@jimi.cs.unlv.edu> maniac@hubert.cs.unlv.edu (Eric J. Schwertfeger) writes:

maniac>   Is it possible to setfunction dos.library?  I have been told
maniac> that the normal setfunction call willnot, but is it possible
maniac> to do a work-around?

In response to the original article, the problem was with programs
opening * as stderr in the startup-sequence.  Let me just suggest to
begin with that you simply use runback to start such programs instead;
then they will try to open null:* instead of con:*.  If it's really
important for you to get stdout and nullify (no pun intended) stderr,
then I guess you can go ahead and deal with SetFunction and
dos.library...  (Read on...)

On 5 Feb 90 22:27:54 GMT, jbickers@actrix.co.nz (John Bickers) said:

jbickers>     Yes, the normal SetFunction() expects a library entry (6
jbickers> bytes in the library table) to be:

jbickers>                 jmp     32-bit address

jbickers>     So when you SetFunction a library vector it returns the
jbickers> top four bytes of the 6 as the function point it's supposed
jbickers> to return, and plugs in the 4-byte pointer you provide. It
jbickers> also seems to re-write the jmp instruction code.

jbickers>     This works fine for most libraries, but the DOS library
jbickers> doesn't have that type of entry. Instead of a jmp to a
jbickers> 32-bit address it has:

jbickers>                 moveq   nn,d0     ; nn is some value DOS understands
jbickers>                 bra.w   DOS routine

jbickers>     The DOS routine is usually the same for all the
jbickers> different "vectors", and it must somehow work out from the
jbickers> value in d0 which DOS function you are calling (go BCPL! :).

I always found it quite annoying that AmigaDOS breaks this simple rule
for Exec libraries...  argh.

jbickers>     So to emulate SetFunction(), you have to write your own
jbickers> code that will replace the moveq,bra sequence with a 32-bit
jbickers> jump to your intercept code, and your intercept code must,
jbickers> at the end, move nn into d0 and then jmp to the destination
jbickers> of the original branch instruction.

jbickers>     You can determine the value of nn and the destination of
jbickers> the original branch instruction by taking a debugger to the
jbickers> DOSBase vector. For example, a do-nothing program in Lattice
jbickers> C was enough for CodeProbe to pick up DOSBase from.

It's an awful kludge, but I suppose you could write your own
SetFunction() which understands both the proper form of the jump
vector, and the form which dos.library uses.

I wouldn't suggest hardcoding the address of the DOS routine as
discovered from a debugger; it might not be consistent across
machines, though it will probably work for a single machine.  (I do
hope dos.library isn't quite so stupid as to have the vector table in
ROM!)

Patch SetFunction (with SetFunction!) to check for a vector entry
consisting of a moveq nn,d0 followed by a bra.w <routine>, and if it
is of that form, AllocMem space for a stub routine consisting of the
moveq nn,d0 followed by a jmp <routine>, and change the original
vector to point to the stub.

The SetFunction patch would have to be able to recognize the moveq and
bra.w opcodes, and also be able to calculate the absolute address of
the <routine> from the address of the original vector and the offset
given in the instruction.

After creating the stub routine and replacing the original vector,
this patch should then call the original SetFunction.  If the vector
is already a jmp instruction, the patch should only call the original
SetFunction.  If the vector is neither jmp or moveq/bra, it should
probably barf.  (assuming there's a defined way for SetFunction to
fail and give an error return (-1?) otherwise, I guess it just has to
call the original SetFunction and let things go to hell.)

Optionally, also patch UnSetFunction to recognize the stub routine
(when it's the target of the to-be-restored vector address) and have
it reconstruct the original moveq/bra sequence in the vector table, or
perhaps have the SetFunction patch save the sequence in the allocated
block for simplicity.

Patching UnSetFunction also would be good for symmetry, but probably
insignificant, as the allocated block would be 16 bytes of memory per
SetFunction'd dos.library call, and such dos patches would probably be
left in, and not backed out.  If they are backed out, then there is a
memory loss, but an insignificant one...  it would only create only
one stub routine for any given call which was SetFunction'd, and at
worst, you'd lose 16*n bytes of memory, where n is the number of
dos.library calls there are.  (what, maybe 50 functions, max?
(probably less)  50 functions would be 800 bytes lost to stub
routines.  Not critical.)

Still, it would be bad form to patch SetFunction but not
UnSetFunction, so both should be done.

I told you it was a kludge.

[I wonder if I should go ahead and write it, though...  it's a kludge,
but could be a useful one.]

Deven
-- 
Deven T. Corzine        Internet:  deven@rpi.edu, shadow@pawl.rpi.edu
Snail:  2151 12th St. Apt. 4, Troy, NY 12180   Phone:  (518) 274-0327
Bitnet:  deven@rpitsmts, userfxb6@rpitsmts     UUCP:  uunet!rpi!deven
Simple things should be simple and complex things should be possible.

marco@alessia.dei.unipd.it (Captain Harlock) (10/19/90)

Sorry, I fault, I will try a new newsgroup:

How can I use SetFunction() with Lattice C 5.05 ?
I should want change OpenWindow() ! But I don't know how made it.

Thank for your help ...
							...marco