home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Tricks of the Mac Game Programming Gurus
/
TricksOfTheMacGameProgrammingGurus.iso
/
Information
/
CSMP Digest
/
volume 1
/
csmp-v1-192.txt
< prev
next >
Encoding:
Amiga
Atari
Commodore
DOS
FM Towns/JPY
Macintosh
Macintosh JP
NeXTSTEP
RISC OS/Acorn
Shift JIS
UTF-8
Wrap
Text File
|
1994-12-08
|
42.6 KB
|
1,248 lines
|
[
TEXT/R*ch
]
C.S.M.P. Digest Tue, 20 Oct 92 Volume 1 : Issue 192
Today's Topics:
Trap intercepts
Apple Events
Porting code using fork() to the Mac
DESPERATE: switching pixmaps w/ SetPortPix
The Comp.Sys.Mac.Programmer Digest is moderated by Michael A. Kelly.
The digest is a collection of article threads from the internet newsgroup
comp.sys.mac.programmer. It is designed for people who read c.s.m.p. semi-
regularly and want an archive of the discussions. If you don't know what a
newsgroup is, you probably don't have access to it. Ask your systems
administrator(s) for details. (This means you can't post questions to the
digest.)
Each issue of the digest contains one or more sets of articles (called
threads), with each set corresponding to a 'discussion' of a particular
subject. The articles are not edited; all articles included in this digest
are in their original posted form (as received by our news server at
cs.uoregon.edu). Article threads are not added to the digest until the last
article added to the thread is at least one month old (this is to ensure that
the thread is dead before adding it to the digest). Article threads that
consist of only one message are generally not included in the digest.
The entire digest is available for anonymous ftp from ftp.cs.uoregon.edu
[128.223.8.8] in the directory /pub/mac/csmp-digest. Be sure to read the
file /pub/mac/csmp-digest/README before downloading any files. The most
recent issues are available from sumex-aim.stanford.edu [36.44.0.6] in the
directory /info-mac/digest/csmp. If you don't have ftp capability, the sumex
archive has a mail server; send a message with the text '$MACarch help' (no
quotes) to LISTSERV@ricevm1.rice.edu for more information.
The digest is also available via email. Just send a note saying that you
want to be on the digest mailing list to mkelly@cs.uoregon.edu, and you will
automatically receive each new issue as it is created. Sorry, back issues
are not available through the mailing list.
Send administrative mail to mkelly@cs.uoregon.edu.
-------------------------------------------------------
From: George.Economou@f120.n129.z1.FIDONET.ORG (George Economou)
Subject: Trap intercepts
Date: Wed, 05 Aug 92 17:27:10 EST
Organization: FidoNet node 1:129/120 - Mac For The Mind, Pittsburgh PA
I am trying to write a trap intercept for waitnextevent. It is contained in
an INIT. The init loads fine and does not crash the system, but it doesn't do
what I installed. Can anyone give me some help via source or other info?
I followed the way they said to do it in MAcintosh Prog. Secrets 2nd edition.
George Economou
- --
George Economou via cmhGate - Net 226 fido<=>uucp gateway Col, OH
UUCP: ...!n8emr!bluemoon!cmhgate!129!120!George.Economou
INET: George.Economou@f120.n129.z1.FIDONET.ORG
+++++++++++++++++++++++++++
From: keith@taligent.com (Keith Rollin)
Date: 10 Aug 92 19:11:37 GMT
Organization: Taligent
In article <936620.2A85E472@cmhgate.fidonet.org>,
George.Economou@f120.n129.z1.FIDONET.ORG (George Economou) writes:
>
> I am trying to write a trap intercept for waitnextevent. It is contained in
> an INIT. The init loads fine and does not crash the system, but it doesn't do
> what I installed. Can anyone give me some help via source or other info?
> I followed the way they said to do it in MAcintosh Prog. Secrets 2nd edition.
Hmmm...then I guess I'd better answer this...
Sorry to lead you astray, George, but I guess we didn't cover all the pitfalls
of patching traps. There are some considerations you have to make with certain
traps. WaitNextEvent is one of them.
The problem is that there are three "kinds" of traps in the Macintosh. Those
that are in ROM, those that are implemented early in the Mac's startup sequence
(before INIT time), and those that are implemented late in the startup sequence
(after INIT).
WaitNextEvent belongs to this third category. What happens is this. The Mac
starts up. It sets some things up, and then runs the INITs. Your INIT runs and
patches WaitNextEvent. Later, the third category of traps are implemented,
wiping out your patch in the process.
There are three things you can do to get around this. In general, what people do
is patch a different trap instead that _won't_ get wiped out to. This second
patch is responsible for patching the trap you really want at a time that's
safe.
Another thing you can do is patch SetTrapAddress to protect your patch. Write
your SetTrapAddress patch to detect when someone tries to over patch your patch.
If it detects that, keep your patch address in the trap table, and store the new
patch address locally. You'll also need to patch GetTrapAddress to return this
local copy if it's asked for.
In your case, you have an easier alternative. Hook into the low-memory global
jGNEFilter. This is a hook that's called just before Get/WaitNextEvent returns
to the caller. Be sure to save all registers, and be sure to chain to any
routines already hooked into jGNEFilter. There's a technote on this that you can
peruse.
Hope this helps,
- --
Keith Rollin
Phantom Programmer
Taligent, Inc.
+++++++++++++++++++++++++++
From: volaski@acsu.buffalo.edu (Maurice Volaski)
Date: 11 Aug 92 14:34:11 GMT
Organization: UB
In article <Bss7zE.26D@taligent.com> keith@taligent.com (Keith Rollin) writes:
>In your case, you have an easier alternative. Hook into the low-memory global
>jGNEFilter. This is a hook that's called just before Get/WaitNextEvent returns
>to the caller. Be sure to save all registers, and be sure to chain to any
>routines already hooked into jGNEFilter. There's a technote on this that you can
>peruse.
There is more...If you want to *modify* the event, then this won't do because
desk accessories get the event before the jGNEFilter. In this case, you would
have to patch SystemEvent, and then that has problems too. Some programs
disable it and others don't even call WaitNextEvent all the time. You could
conceivably be left with having to tail-patch OSEventAvail and GetOSEvent :-(
Maurice Volaski
---------------------------
From: francois@welchgate.welch.jhu.edu (Francois Schiettecatte)
Subject: Apple Events
Organization: Johns Hopkins Univ. Welch Medical Library
Date: Tue, 16 Jun 1992 18:17:36 GMT
Hi
When an application receives an Apple Event how can
it uniquely identify the process/machine
that sent it. I am sure that this information
is available in the AE but I have not found out
how to get it out of there.
francois
Francois Schiettecatte
Software Engineer
Welch Medical Library
Johns Hopkins University
Internet: francois@library.welch.jhu.edu
Phone : (410) 955-7581
+++++++++++++++++++++++++++
From: kamprath@caen.engin.umich.edu (Michael F. Kamprath)
Date: Sat, 11 Jul 92 14:50:39 EDT
Organization: University of MIchigan
For the longest time, I thought something was wrong with my program when I
would get an noOutstandingHLE error when ever I would want to proccess an
Apple Event. But, I then turned off the debugger on THINK C 5, and low and
behold, my program no longer had troubles.
So, why can't my program (actually, project) receive high level events when
I am also using the THINK C Debugger? Is this a bug in the debugger, or
am I doing something wrong?
Michael Kamprath
kamprath@caen.engin.umich.edu
+++++++++++++++++++++++++++
From: gwatts@cdf34.fnal.gov (Gordon Watts -- U of Rochester)
Organization: Fermilab
Date: Tue, 14 Jul 1992 15:11:15 GMT
In article <xCM-SG+@engin.umich.edu>, kamprath@caen.engin.umich.edu (Michael F. Kamprath) writes...
>For the longest time, I thought something was wrong with my program when I
>would get an noOutstandingHLE error when ever I would want to proccess an
>Apple Event. But, I then turned off the debugger on THINK C 5, and low and
>behold, my program no longer had troubles.
>
Hi,
When using Think C debugger with AEs, I've found two things of use. First,
think doesn't preserve (when running the debugger) the creator id, so address
made with the application's signature won't work right. I stumbled on this
when using self-aes, but you may also have this problem. I've been using
process ids for a while now, and that all seems to work.
Second thing has to do with time-outs. Don't set a break in your event
loop when sending aes. If you do, and the apple event is sent with a
timeout (2 seconds or something like that), by the time you hit "go" from
the break point, 2 seconds have passed and the apple event is unqueued. Break
points in the handlers are fine. Or, I guess, you could put an infinite
timeout on your AESend call.
Cheers,
Gordon.
+++++++++++++++++++++++++++
From: mxmora@unix.sri.com (Matthew Xavier Mora)
Date: 14 Jul 92 16:58:37 GMT
Organization: SRI International
I want my CD player program to be scriptable and to support
appleEvents. I did a quick browse of the Apple event registry
and did not see anything I could use. Is there some kind of media
event type that has been defined that I missed? I'm looking for event
types like play, pause, stop, rewind, fast forward and QueToHere. You
would think that Apple has define something like this for Quicktime or for
controlling movies or a video disk player.
Are there such apple events?
Thanks
Matt
+++++++++++++++++++++++++++
From: pete@aurora.rice.edu (Louis Wu)
Organization: Whatsamatta U
Date: Tue, 14 Jul 1992 20:58:32 GMT
In article <14JUL92091115@cdf34.fnal.gov> gwatts@cdf34.fnal.gov (Gordon Watts -- U of Rochester) writes:
In article <xCM-SG+@engin.umich.edu>, kamprath@caen.engin.umich.edu (Michael F. Kamprath) writes...
>For the longest time, I thought something was wrong with my program when I
>would get an noOutstandingHLE error when ever I would want to proccess an
>Apple Event. But, I then turned off the debugger on THINK C 5, and low and
>behold, my program no longer had troubles.
>
Hi,
When using Think C debugger with AEs, I've found two things of use. First,
think doesn't preserve (when running the debugger) the creator id, so address
made with the application's signature won't work right. I stumbled on this
when using self-aes, but you may also have this problem. I've been using
process ids for a while now, and that all seems to work.
True, but you can still send apple events to the program being debugged by
addressing the event to the name of your project.
- --
=============================================================================
Pete Keleher "Relax! Don't worry! Have a homebrew!" pete@cs.rice.edu
=============================================================================
+++++++++++++++++++++++++++
From: leonardr@ccs.itd.umich.edu
Organization: Campus Computing Sites, University of Michigan-Ann Arbor
Date: Wed, 15 Jul 92 01:47:57 GMT
In article <mxmora-140792095215@css-mac1.sri.com> mxmora@unix.sri.com (Matthew Xavier Mora) writes:
>I want my CD player program to be scriptable and to support
>appleEvents. I did a quick browse of the Apple event registry
>and did not see anything I could use. Is there some kind of media
>event type that has been defined that I missed? I'm looking for event
>types like play, pause, stop, rewind, fast forward and QueToHere. You
>would think that Apple has define something like this for Quicktime or for
>controlling movies or a video disk player.
>
>Are there such apple events?
>
Last time I checked with John Pugh (kAERegistrar) they had not yet
developed a Quicktime suite, or a "media" suite. You might want to check a
again (or John could chime in ;).
If you don't want to wait for the folks at Apple, you might want to
develop your own custom events for the first version of your software and
then update in the future with the "standard" events.
- --
- -----------------------------------------------------------------------
Leonard Rosenthol Internet: leonardr@ccs.itd.umich.edu
Director of Advanced Technology AppleLink: MACgician
Aladdin Systems, inc. GEnie: MACgician
+++++++++++++++++++++++++++
From: eric_gorr@coglab_psych.uoregon.edu (Eric Gorr)
Organization: University of Oregon Network Services
Date: Wed, 22 Jul 92 20:44:11 GMT
I was wondering if someone could point me to or send me some sample code
which demonstrates how to implement some application-specific events.
Basically what I am doing is writing an application that I would like to be
able to run via apple-events.
(I would prefer the code be a complete (simple) application...)
thanx...
+++++++++++++++++++++++++++
From: jpugh@apple.com (Jon Pugh)
Date: 19 Jul 92 00:26:30 GMT
Organization: Apple Computer, Inc.
In article <mxmora-140792095215@css-mac1.sri.com>, mxmora@unix.sri.com (Matthew Xavier Mora) writes:
>
> I want my CD player program to be scriptable and to support
> appleEvents. I did a quick browse of the Apple event registry
> and did not see anything I could use. Is there some kind of media
> event type that has been defined that I missed? I'm looking for event
> types like play, pause, stop, rewind, fast forward and QueToHere. You
> would think that Apple has define something like this for Quicktime or for
> controlling movies or a video disk player.
>
> Are there such apple events?
There are no such events currently defined. Several people are interested
in creating such events, but no one has taken the responsibility of doing it.
Since all suites have to go through me to become offical, the first one to
get something to me that will work will get it done their way (if I approve).
James "im" Beninghaus of DTS is going to be redoing his CD Remote to support
AE soon. You might want to collaborate with him to define some standards.
We've been talking about some of the things that would be necessary. His
address is BENINGHAUS@Applelink.Apple.Com. Tell him that I sent you.
Once an appropriate spec gets written and approved by me and some cohorts,
we will post it on ftp.apple.com and Applelink. New suites should also
appear on the Dev CDs as they are defined.
People are still climbing the learning for AE, but I am talking to more and
more people who are doing things correctly. It is very encouraging. The
time of Apple Events is approaching rapidly.
Jon Pugh
kAERegistrar
+++++++++++++++++++++++++++
From: yjc@po.cwru.edu (Jerome Chan)
Date: 30 Jul 92 17:37:43 GMT
Organization: Alethea, The Twilight World!
I have just ftped down the Winter 92 Apple Events Registery and I am
confused. What are Object Classes?
- ---
The Evil Tofu
"No Lah! Sure or not one? Dunno leh! Nebber Mind! Like that one!
Terriblur Lah!"
+++++++++++++++++++++++++++
From: jpugh@apple.com (Jon Pugh)
Date: 2 Aug 92 17:32:15 GMT
Organization: Apple Computer, Inc.
In article <1992Jul30.173743.8571@usenet.ins.cwru.edu>, yjc@po.cwru.edu
(Jerome Chan) wrote:
>
>
> I have just ftped down the Winter 92 Apple Events Registery and I am
> confused. What are Object Classes?
As we have discussed in email, I will elucidate for the faceless masses.
For anyone interested in doing serious AppleEvent development using the
object model as described in the Apple Event Registry: Standard Suites,
you should get a copy of the Developer CD and read the Collaborative
Computing chapter of the New Inside Macintosh. This rolls all the AE
documentation into one place and makes it understandable (well, as
understandable as we can make it).
This new version of Inside Mac is coming slowly to stores near you. It
is well worth the cost of replacing your current IM. Imagine all of QD
in one volume. Imagine all the File Manager chapters rolled into one.
Imagine all the Tech Notes eliminated because Inside Mac states all the
necessary information.
Cool huh?
Jon
+++++++++++++++++++++++++++
From: MScott@FirstClass.COM (M. Scott Marcy)
Date: 12 Aug 92 16:35:33 GMT
Organization: First Class Systems, Inc.
Hi,
Well, I'm just adding support for AppleEvents to my program, and I need
to reply to the open document event under certain circumstances (I can
only open one document at a time). I want to send an error string back
to the source application, so I followed the procedures in both Inside
Mac VI (page 6-49, Listing 6-12) and AEObject-Edition Sample (in
AppleEventCore.c). From all I can tell, I'm doing exactly the same
thing, but my call to AEPutParamPtr/Desc returns an error -1704
(errAENotAEDesc). I checked the reply record, which contains a 'null'
descriptor. All the sample code shows that I should just call
AEPutParamXXX to store my error string in the reply record--no other
setup or initialization of the reply record is required.
What gives? I've looked everywhere I can think of on this one and
haven't found any example other than adding the string directly to the
reply event given to the event handler.
BTW: I've tried both AEPutParamPtr (as in the examples) and
AEPutParamDesc, both with the same result. The code below has the
AEPutParamDesc version.
Scott Marcy
First Class Systems, Inc.
ALink: FIRST.CLASS
InterNET: MScott@FirstClass.COM (Preferred)
==========================================================================
Here's the code from my open document handler. The CHECK, FAIL,
ERR_HANDLER stuff is for collecting and handling errors. Everything else
should be (relatively) standard.
pascal OSErr miae_open_doc(AppleEvent *event, AppleEvent *reply, long ref)
{ ERR_HEADER
#pragma unused (ref)
Boolean empty, have_list = FALSE, have_desc = FALSE;
AEDescList doc_list;
AEDesc desc;
AEKeyword keyword; /* ignored */
DescType type; /* ignored */
Size size; /* ignored */
long num_items;
FSSpec file_spec;
Str255 err_str;
Str63 name;
short wd;
/* Get the required parameters */
CHECK(AEGetParamDesc(event, keyDirectObject, typeAEList, &doc_list));
have_list = TRUE;
/* Make sure there are no more required parameters */
CHECK(miae_got_all_params(event, &empty));
if (!empty)
FAIL(errAEEventNotHandled);
/* Count the number of files sent to us */
CHECK(AECountItems(&doc_list, &num_items));
/* We can only open one document, otherwise return an error */
if (num_items > 1) {
/* Get an error string */
GetIndString(err_str, rErrorStrings, iMultOpenErr);
CHECK(AECreateDesc(typeChar, (Ptr) &err_str[1], err_str[0], &desc));
have_desc = TRUE;
CHECK(AEPutParamDesc(reply, keyErrorString, &desc));
CHECK(AEDisposeDesc(&desc)); have_desc = FALSE;
FAIL(errAEEventNotHandled); }
else if (num_items == 1) {
/* Open the one database specified */
CHECK(AEGetNthPtr(&doc_list, 1, typeFSS, &keyword, &type,
(Ptr) &file_spec, sizeof(file_spec), &size));
/* Make a working directory reference for our open routine */
CHECK(OpenWD(file_spec.vRefNum, file_spec.parID, FCGB_CREATOR, &wd));
p_to_c_string(file_spec.name, name);
CHECK(mi_open_database(wd, name, FALSE));
CHECK(CloseWD(wd)); }
/* Release the document list handle */
CHECK(AEDisposeDesc(&doc_list)); have_list = FALSE;
ERR_HANDLER
if (have_list)
AEDisposeDesc(&doc_list);
if (have_desc)
AEDisposeDesc(&desc);
ERR_HANDLER_END
} /* End: miae_open_doc */
+++++++++++++++++++++++++++
From: lai@Apple.COM (Ed Lai)
Date: 12 Aug 92 20:04:44 GMT
Organization: Apple Computer Inc., Cupertino, CA
The reply is null because the client is not looking for a reply. If it
is null, don't bother to reply.
/* Disclaimer: All statments and opinions expressed are my own */
/* Edmund K. Lai */
/* Apple Computer, MS37-UP */
/* 20525 Mariani Ave, */
/* Cupertino, CA 95014 */
/* (408)974-6272 */
zW@h9cOi
+++++++++++++++++++++++++++
From: johnl@spinner.cs.indiana.edu (John Lacey)
Date: 26 Aug 92 20:17:25 GMT
Organization: Computer Science, Indiana University
I am trying to get a simple app with Apple events going, but I can't
even get by the Open Application event.
Problem #1: Using the code snippets from IM VI, the call to
AEGetAttributePtr returns errAENotAEDesc. The only thing I did was
call AEProcessAppleEvent, and call AEGetAttributePtr first thing in my
handler.
Problem #2: Is there any way to debug Apple event handlers in Think C
5.0? If I run under Think C, AEProcessAppleEvent returns
noOutstandingHLE. No such problems with the built application.
What am I missing, and is there a good reference for this, or some
example code?
- --
John Lacey `Everything must end; meanwhile we
must amuse ourselves.' --Voltaire
---------------------------
From: dat@ukc.ac.uk (D.A.Turner)
Subject: Porting code using fork() to the Mac
Date: 5 Aug 92 13:00:24 GMT
Organization: Computing Lab, University of Kent at Canterbury, UK.
I am interested in porting a medium size (c. 10k lines of source) piece
of software developed in C under UNIX to the Mac environment. The user
interface will need to be rewritten, but there is another problem, which
I wondered if anyone on this newsgroup can advise me about?
My C code uses *fork* quite a bit. Does anyone know of a C environment
for the Mac which supports fork() or provides some equivalent facility?
I don't need true concurrency - in all my uses of fork() the parent
waits for the child to finish before resuming control. (In other words
I am using fork to provide the child with its own copy of state space
which it can write all over without disturbing the state of the parent.)
Is there a way to do this under the Mac O/S? Rewriting my code to get
rid of fork() would be very tedious and I would prefer to avoid that.
Thanks in advance for any help - I will summarise to the net if I get
any useful info.
David Turner
University of Kent, England
+++++++++++++++++++++++++++
From: mikeb@sam.amgen.com (Michael Brennan)
Date: 14 Aug 92 18:15:03 GMT
Organization: Amgen
In article <503@owl.ukc.ac.uk> D.A.Turner, dat@ukc.ac.uk writes:
>My C code uses *fork* quite a bit. Does anyone know of a C environment
>for the Mac which supports fork() or provides some equivalent facility?
Apple has released a "Threads" library on its developer CDs. It's use is
documented
in issue 6 of Develop. It has a calling syntax very similar to fork()
and (from
what I've been able to tell) appears to be quite robust.
The library itself is an MPW .o file with no source available, but I was
able
to convert it to a Think C library using oConv with no difficulty. If
you have
access to Develop CDs or know anyone who does, I recommend getting ahold
of the
Threads library.
+++++++++++++++++++++++++++
From: orpheus@reed.edu (P. Hawthorne)
Date: 16 Aug 92 00:10:18 GMT
Organization: Reed College, Portland, OR
mikeb@sam.amgen.com, Michael Brennan, writes:
: Apple has released a "Threads" library on its developer CDs. It's use is
: documented in issue 6 of Develop. It has a calling syntax very similar to
: fork() and (from what I've been able to tell) appears to be quite robust.
If imitation is the sincerest form of flattery, then a failed attempt at
imitation is the most telling. I, rather unsuccessfully, tried to take the
same approach to a threading package for Object Pascal. It was like trying
to walk on eggshells, and still make the perfect omelette.
In the docs, there is some interesting discussion of a scheme for marking
all unused code resources purgeable. The idea was to mark all code
resources purgeable with the obvious exception of one resource, followed by
a walk of the stack looking for anything resembling a return address, so
that the relevant resources could be marked as non-purgeable.
Has anyone given that a shot?
Theus (orpheus@reed.edu)
+++++++++++++++++++++++++++
From: heksterb@cs.utwente.nl (Ben Hekster)
Organization: University of Twente, Dept. of Computer Science
Date: Sun, 16 Aug 1992 08:36:56 GMT
In article <1992Aug16.001018.26666@reed.edu> orpheus@reed.edu (P. Hawthorne) writes:
> In the docs, there is some interesting discussion of a scheme for marking
>all unused code resources purgeable. The idea was to mark all code
>resources purgeable with the obvious exception of one resource, followed by
>a walk of the stack looking for anything resembling a return address, so
>that the relevant resources could be marked as non-purgeable.
Hey, I do this! And you say this scheme is actually documented
somewhere? It's exactly as you describe-- I keep all but a few 'CODE'
segments purgeable, and install a grow zone function that scans the
stack for addresses within these segments. Any segment that
isn't referenced from the stack is unloaded from the gz function.
I know it sounds skanky but it works great!
Obvious advantages: I never ever have to worry about calling
UnloadSeg again, so I can resegment my applications at any time without
having to worry about whether I'm doing UnloadSeg calls in the right
order and in the right place, and since I'm also not doing UnloadSeg
in the main event loop on every CODE segment, there is zero overhead,
if you have enough memory.
Disadvantage: Could fail under Pink.
- --
Ben `Hackster' Hekster | "He bides his time and thinks,
heksterb@cs.utwente.nl | 'There must be more to life than this!'"
+++++++++++++++++++++++++++
From: d88-jwa@dront.nada.kth.se (Jon W{tte)
Organization: Royal Institute of Technology, Stockholm, Sweden
Date: Sun, 16 Aug 1992 20:35:10 GMT
.edu> orpheus@reed.edu (P. Hawthorne) writes:
In the docs, there is some interesting discussion of a scheme for marking
all unused code resources purgeable. The idea was to mark all code
resources purgeable with the obvious exception of one resource, followed by
a walk of the stack looking for anything resembling a return address, so
that the relevant resources could be marked as non-purgeable.
Has anyone given that a shot?
Don't forget the registers ! And the stacks for all OTHER threads !
However, that's exactly how many garbage collection schemes work
in various dynamic languages (such as LISP)
- --
- - I have decided that it is not boxes but my lack of skill that's the problem.
- - Traitor! This kind of attitude will get you nowhere around here. If you must
know, it's not your boxes that are the problem, it's your lack of a
sufficient number of boxes. Go out and buy something.
+++++++++++++++++++++++++++
From: heksterb@cs.utwente.nl (Ben Hekster)
Date: 18 Aug 92 11:34:22 GMT
Organization: University of Twente, Dept. of Computer Science
Hi--
I had a couple of requests to post my CODE segment-unloading grow zone
function, so here it is.
As you can see, it's actually written in C++ (the Language of
the Gods), not in Assembly. I've taken this code out of my class
library and extracted just (hopefully) all the relevant bits. The
conversion to C shouldn't be much of a problem. Though I suppose some
people may find it rather sparsely commented, that's the way I like
it. I prefer to think that it's self-documenting...
I wouldn't necessarily mind rewriting it in 68000 if I thought
it was worth it. I haven't done any profiling on this code, so I'm not
yet convinced that it would be, though I can see some nested loops in
there and some possible `optimizations'.
The reason why this doesn't really bother me is that the grow
zone function doesn't get called often, and only when you are operating
close to the limit of available memory. One of the neat things about
this scheme is that you will never get called nor will any segment ever
be unloaded if you have enough memory available. You only start paying
a performance penalty when you are nearly out of memory, which seems
reasonable.
Remember, if you use this, you probably never have to call
UnloadSeg again. Just mark any segments that you want to allow to be
purged as `purgeable'. You may want to keep certain frequently used
segments resident (i.e., preload and not purgeable). You MUST NOT make
the segment containing the grow zone function itself purgeable.
Of course, if you can spot any problems with this, I'd be
obliged if you'd let me know about them. I can come up with some
scenarios that might cause this to fail but they seem rather unlikely.
In particular I can't find it documented anywhere whether I can
actually count on A5 being valid in the gzProc. I suppose that comes
down to not making any Memory Manager calls without A5 being valid,
but I don't think that's legal, so it looks like I'm safe.
All I can say is that I and several beta testers have been
using this code in an application of mine for several months now
without any apparent problems. Use at your own risk, &c. &c.
Enjoy!
P.S.: View this code with an 8-character tab width. Some of the lines
are longer than 80 characters, but I've let them wrap instead
of inserting line breaks or `fmt'ing the code
- ----- begins
class TApplication {
protected:
static pascal long GrowZone(Size cbNeeded); // grow zone function
struct AddressRange { void *start, *end; }; // location of CODE in memory
short fNumCODEResources; // number of CODE resources
AddressRange *fCODEAddresses; // CODE addresses
public:
static TApplication *gApplication; // last instantiated application
};
/* TApplication
Application constructor
*/
#pragma segment Initialization
TApplication::TApplication()
{
fCODEAddresses = NULL;
// etc.
...
// install grow zone function
fNumCODEResources = Count1Resources('CODE');
fCODEAddresses = (AddressRange*) NewPtr(fNumCODEResources * sizeof(AddressRange)); mfault;
if (fCODEAddresses)
SetGrowZone(&TApplication::GrowZone);
// leave a pointer for anyone to find me
gApplication = this;
}
/* ~TApplication
*/
#pragma segment Termination
TApplication::~TApplication()
{
if (fCODEAddresses) DisposPtr((Ptr) fCODEAddresses);
}
/* CurrentA5
Returns the current value of A5
*/
#pragma parameter __D0 CurrentA5
void *CurrentA5() = 0x200d; // MOVE.L A5,D0
/* CurrentA7
Returns the current value of A7
*/
#pragma parameter __D0 CurrentA7
void *CurrentA7() = 0x200f; // MOVE.L A7,D0
/* GrowZone
Grow zone function
*/
#pragma segment Main
pascal long TApplication::GrowZone(
Size cbNeeded // bytes needed
)
{
(void) cbNeeded; // not used
long unloadedSome = 0;
register AddressRange *codeAddress;
register short i;
void *mask = StripAddress((Ptr) 0xffffffff);
// find all purgeable but locked CODE resources in memory
register short numCODEResources = gApplication->fNumCODEResources;
char saveResLoad = *(char*) 0x0a5e; // from SysEqu.h
SetResLoad(false);
for (i = 1, codeAddress = gApplication->fCODEAddresses; i <= numCODEResources; i++, codeAddress++) {
codeAddress->start = NULL;
// is the resource in memory?
Handle codeH = Get1IndResource('CODE', i);
if (codeH && *codeH)
// is it a purgeable but locked resource?
if ((HGetState(codeH) & 0xe0) == 0xe0) {
// how big is it?
Size codeSize = GetHandleSize(codeH);
if (codeSize > 0) {
// record the address range so it is eligible for purging
codeAddress->start = (void*) ((long) *codeH & (long) mask);
codeAddress->end = (char*) codeAddress->start + codeSize;
}
}
}
if (saveResLoad) SetResLoad(true);
// examine the stack
Zone &applZone = *ApplicZone();
enum { CurStackBase = 0x0908 };
void
*stackTop = CurrentA7(), // stack to search
*stackBase = *((void**) CurStackBase),
*heapStart = &applZone.heapData, // application zone data
*heapEnd = applZone.bkLim;
// search the stack for references to loaded segments
enum { CurJTOffset = 0x0934 };
for (register char *a7 = (char*) stackTop; a7 < stackBase; a7 += 2) {
// is the address on the stack within the application heap?
register void *stackData = (void*) (*(long*) a7 & (long) mask);
if (stackData >= heapStart && stackData < heapEnd)
// is it in any of the code segments?
for (i = 1, codeAddress = gApplication->fCODEAddresses; i < numCODEResources; i++, codeAddress++)
if (codeAddress->start && stackData >= codeAddress->start && stackData < codeAddress->end) {
// exclude it from unloading
codeAddress->start = NULL;
break;
}
}
// unload everything that wasn't referenced inside the stack
for (i = 1, codeAddress = gApplication->fCODEAddresses; i < numCODEResources; i++, codeAddress++)
// may we unload it?
if (codeAddress->start) {
// ready to get it on!
UnloadSeg((char*) CurrentA5() +
(*(short*) CurJTOffset) + // beginning of jump table
(*(short*) codeAddress->start) + // segment's first entry in jump table
2 // routine address
);
unloadedSome++;
}
return unloadedSome;
}
- ----- ends
- --
Ben `Hackster' Hekster | "He bides his time and thinks,
heksterb@cs.utwente.nl | 'There must be more to life than this!'"
---------------------------
From: envy@reed.edu!envy.Reed.Edu!pcalahan (Patrick John Calahan)
Subject: DESPERATE: switching pixmaps w/ SetPortPix
Date: 6 Aug 92 16:12:10 GMT
Organization: Reed College, Portland, OR
I still need a few lines of code which will do the following.
SetPortPix(myOffscreenPixMap);
blah blah draw
SetPortPix(backToNormalScreenPixMap);
Has anyone done this, and if so, can you help me? I think my problem is
in getting back to the screen, but I've managed to thouroughly confuse
myself.
Any help is very much appreciated....
pcalahan@reed.edu
+++++++++++++++++++++++++++
From: k044477@hobbes.kzoo.edu (Jamie R. McCarthy)
Organization: Kalamazoo College
Date: Fri, 7 Aug 1992 16:24:22 GMT
envy@reed.edu!envy.Reed.Edu!pcalahan (Patrick John Calahan) writes:
>I still need a few lines of code which will do the following.
>SetPortPix(myOffscreenPixMap);
>blah blah draw
>SetPortPix(backToNormalScreenPixMap);
Here's some code I wrote last year that did the trick for me. I've
made it into ThC version 5 code, but I'm not sure if I've ever tested it
in exactly this form. It should work anyway. (Comments on this code
are welcome!)
It's set up to use with an object, but it won't be too hard un-OOPify
it. The instance variables "itsPixMap" and "itsDIInfoHndl" you'll have
to deal with yourself--in the old version, I passed a (PixMap*) to the
startDrawing() routine, and it returned a diInfoHndl, which was the
parameter passed to the stopDrawing() routine.
/* The "drawing-into" information struct. */
typedef struct {
RGBColor oldForeColor, oldBackColor;
GrafPtr oldGrafPtr;
CGrafPort theCGrafPort;
PixMapHandle oldPortPMHndl, newPortPMHndl;
} diInfo, *diInfoPtr, **diInfoHndl;
void CPixMap::startDrawingInto(void)
{
register diInfoPtr theDIInfoPtr;
Boolean portWasOpened = FALSE;
extern RGBColor gRGBBlack, gRGBWhite;
TRY {
itsDIInfoHndl = (diInfoHndl) NewHandleClear( sizeof(diInfo) );
FailNIL(itsDIInfoHndl);
MoveHHi((Handle) itsDIInfoHndl);
HLock((Handle) itsDIInfoHndl);
theDIInfoPtr = *itsDIInfoHndl;
theDIInfoPtr->newPortPMHndl = (PixMapHandle) NewHandle( sizeof(PixMap) );
FailNIL(theDIInfoPtr->newPortPMHndl);
GetForeColor(&theDIInfoPtr->oldForeColor);
GetBackColor(&theDIInfoPtr->oldBackColor);
GetPort(&theDIInfoPtr->oldGrafPtr);
RGBForeColor(&gRGBBlack);
RGBBackColor(&gRGBWhite);
OpenCPort(&theDIInfoPtr->theCGrafPort);
theDIInfoPtr->oldPortPMHndl = theDIInfoPtr->theCGrafPort.portPixMap;
**(theDIInfoPtr->newPortPMHndl) = this->itsPixMap;
theDIInfoPtr->theCGrafPort.portPixMap = theDIInfoPtr->newPortPMHndl;
portWasOpened = TRUE;
SetPort((GrafPtr) &theDIInfoPtr->theCGrafPort);
RGBForeColor(&gRGBBlack);
RGBBackColor(&gRGBWhite);
HUnlock( (Handle) itsDIInfoHndl );
} CATCH {
if (itsDIInfoHndl != NULL) {
if (portWasOpened) {
(**itsDIInfoHndl).theCGrafPort.portPixMap = (**itsDIInfoHndl).oldPortPMHndl;
CloseCPort(&(**itsDIInfoHndl).theCGrafPort);
}
if ((**itsDIInfoHndl).newPortPMHndl != NULL) {
DisposHandle( (Handle) (**itsDIInfoHndl).newPortPMHndl);
}
ForgetHandle(itsDIInfoHndl);
}
} ENDTRY;
}
void CPixMap::stopDrawingInto(void)
{
diInfoPtr theDIInfoPtr;
HLock( (Handle) itsDIInfoHndl );
theDIInfoPtr = *itsDIInfoHndl;
theDIInfoPtr->theCGrafPort.portPixMap = theDIInfoPtr->oldPortPMHndl;
DisposHandle((Handle) theDIInfoPtr->newPortPMHndl);
CloseCPort(&theDIInfoPtr->theCGrafPort);
SetPort(theDIInfoPtr->oldGrafPtr);
RGBForeColor(&theDIInfoPtr->oldForeColor);
RGBBackColor(&theDIInfoPtr->oldBackColor);
ForgetHandle(itsDIInfoHndl);
}
- --
Jamie McCarthy Internet: k044477@kzoo.edu AppleLink: j.mccarthy
Sure, I subscribe to alt.sex, but I only read it for the articles...
+++++++++++++++++++++++++++
From: k044477@hobbes.kzoo.edu (Jamie R. McCarthy)
Organization: Kalamazoo College
Date: Fri, 7 Aug 1992 17:19:09 GMT
There's at least one bug in my drawing-into-a-pixmap code:
>typedef struct {
> ...
> CGrafPort theCGrafPort;
> ...
>} diInfo, *diInfoPtr, **diInfoHndl;
>
>void CPixMap::startDrawingInto(void)
>{
> ...
> itsDIInfoHndl = (diInfoHndl) NewHandleClear( sizeof(diInfo) );
> ...
> HUnlock( (Handle) itsDIInfoHndl );
> ...
>}
As we all know (blush) system data structures that you refer to with a
pointer typically must be non-relocatable. This includes sound
channels, entries in the vertical blanking queue...and GrafPorts.
Take out the HUnlock at the end of startDrawingInto(), and you can
remove the HLock() at the start of stopDrawingInto() as well. I threw
those in just before saving the article, thinking "hmmmm, I wonder why
I wanted to fragment memory like that?" I should trust myself. :-)
- --
Jamie McCarthy Internet: k044477@kzoo.edu AppleLink: j.mccarthy
He let the contents of the bottle do the thinking
Can't shake the devil's hand and say you're only kidding - TMBG
+++++++++++++++++++++++++++
From: ralph@merlin.anu.edu.au (Ralph Sutherland)
Organization: Mt. Stromlo and Siding Spring Observatories
Date: Thu, 13 Aug 92 07:00:30 GMT
Newsgroups: comp.sys.mac.programmer
Subject: Re: DESPERATE: switching pixmaps w/ SetPortPix
Summary:
Expires:
References: <m0mGARZ-0003hxC@envy.reed.edu>
Sender:
Followup-To:
Distribution:
Organization: Mt. Stromlo and Siding Spring Observatories
Keywords:
In Article 21019 in comp.sys.mac.programmer:
envy@reed.edu!envy.Reed.Edu!pcalahan (Patrick John Calahan) Wrote:
>I still need a few lines of code which will do the following.
>
>SetPortPix(myOffscreenPixMap);
>
I tried email but it bounced and there didn't ssem to be any further posts
So...
Is this pseudocode more useful? (excuse the tabs, and as always no guarantees):
variables:
aPort:Grafptr; {general purpose port vriable}
Coffport:CGrafPtr; {temp colour port}
oldpix:PixMapHandle; {save the old pixmap}
offpix:PixMapHandle; {offscreen pixmap, initialised elsewhere}
pwidth,pheight:integer; {offscreen size}
r:rect; {offscreen size}
anRGB:RGBColor; {anRGB color!}
.
.
.
GetPort(aPort);
Coffport := nil; {paranoia}
Coffport := cGrafPtr(NewPtr(sizeof(cGrafport)));
{allocate temp port to hold pixmap}
if (Coffport <> nil)) and (Memerror = Noerr) then {Always check....}
begin
OpenCPort(Coffport); {init port}
oldpix := Coffport^.portPixMap; {save pixmap}
setport(Grafptr(CoffPort)); {set port is a good idea}
SetPortpix(offpix); {use the offpix}
portsize(pwidth, pheight); {Size IS important}
rectrgn(CoffPort^.VisRgn, r); {needed if the pixmap is
larger than the screen}
cliprect(r); { just so we have a clip}
with anRGB do
begin
red := $C000;
green := $C000;
blue := $4000;
end;
RGBForeColor(anRGB); {sort of yellow...}
Fillrect(brect, black); {solid colour}
SetPortpix(oldpix); {put back the pix,
I don't know if you really
have to restore the visrgn}
setPort(aPort); { move to another port
*before* you dispose!}
CloseCPort(CoffPort); {dispose}
disposPtr(Pointer(CoffPort)); {clean Up}
end;
.
.
.
Hope this helps
cheers
Ralph Sutherland
- --
- ---- Ralph S. Sutherland Mount Stromlo & Siding Spring Observatories.
- ---- ralph@madras.anu.edu.au The Australian National University.
- ---- rss100@cscgpo.anu.edu.au --------------------------------------------
+++++++++++++++++++++++++++
From: ralph@mozart.anu.edu.au (Ralph Sutherland)
Organization: Mt. Stromlo and Siding Spring Observatories
Date: Thu, 13 Aug 92 06:49:45 GMT
In Article 21019 in comp.sys.mac.programmer:
envy@reed.edu!envy.Reed.Edu!pcalahan (Patrick John Calahan) Wrote:
>I still need a few lines of code which will do the following.
>
>SetPortPix(myOffscreenPixMap);
>
I tried email but it bounced and there didn't ssem to be any further posts
So...
Is this pseudocode more useful? (excuse the tabs, and as always no guarantees):
variables:
aPort:Grafptr; {general purpose port vriable}
Coffport:CGrafPtr; {temp colour port}
oldpix:PixMapHandle; {save the old pixmap}
offpix:PixMapHandle; {offscreen pixmap, initialised elsewhere}
pwidth,pheight:integer; {offscreen size}
r:rect; {offscreen size}
anRGB:RGBColor; {anRGB color!}
.
.
.
GetPort(aPort);
Coffport := nil; {paranoia}
Coffport := cGrafPtr(NewPtr(sizeof(cGrafport)));
{allocate temp port to hold pixmap}
if (Coffport <> nil)) and (Memerror = Noerr) then {Always check....}
begin
OpenCPort(Coffport); {init port}
oldpix := Coffport^.portPixMap; {save pixmap}
setport(Grafptr(CoffPort)); {set port is a good idea}
SetPortpix(offpix); {use the offpix}
portsize(pwidth, pheight); {Size IS important}
rectrgn(CoffPort^.VisRgn, r); {needed if the pixmap is
larger than the screen}
cliprect(r); { just so we have a clip}
with anRGB do
begin
red := $C000;
green := $C000;
blue := $4000;
end;
RGBForeColor(anRGB); {sort of yellow...}
Fillrect(brect, black); {solid colour}
SetPortpix(oldpix); {put back the pix,
I don't know if you really
have to restore the visrgn}
setPort(aPort); { move to another port
*before* you dispose!}
CloseCPort(CoffPort); {dispose}
disposPtr(Pointer(CoffPort)); {clean Up}
end;
.
.
.
Hope this helps
cheers
Ralph Sutherland
- --
- ---- Ralph S. Sutherland Mount Stromlo & Siding Spring Observatories.
- ---- ralph@madras.anu.edu.au The Australian National University.
- ---- rss100@cscgpo.anu.edu.au --------------------------------------------
---------------------------
End of C.S.M.P. Digest
**********************