Path: utzoo!attcan!utgpu!jarvis.csri.toronto.edu!mailrus!csd4.milw.wisc.edu!cs.utexas.edu!uunet!mcvax!kth!draken!tut!santra!jmunkki From: jmunkki@santra.UUCP (Juri Munkki) Newsgroups: comp.sys.mac.programmer Subject: Having Fun? [Re: Standard File and Desk Accessories] Keywords: Globals, Party, Enough! Message-ID: <22694@santra.UUCP> Date: 9 Jun 89 11:30:51 GMT References: <4972@umd5.umd.edu> <2026@husc6.harvard.edu> Organization: Helsinki University of Technology, Finland Lines: 94 siegel@endor.harvard.edu (Rich Siegel) writes: > earleh@eleazar.dartmouth.edu (Earle R. Horton) writes: > > This looks like fun! > It IS fun. I have to agree. > For example, suppose you have an INIT and a cdev that need to > share information with one another? How do you propose to have them > communicate? Remember, there's no low memory you can use, and there's > no place to place a base register. Well, you could put a block in the > system heap with your unique signature in it, and crawl the system > heap for it, BUT that (a) won't work when the format of heap blocks > changes, and (b) won't work when the system heap becomes protected. That's the technique that is described in the QuicKeys manual. I've also used it on one occasion, but I know of a better way to do it. There's only one problem with the better way and it's that it isn't always possible (and it doesn't work with old systems). The solution is to use AppleTalk. If you Mac isn't connected to a network, this doesn't work, but in my case I was writing a program that already required an AppleTalk network. My INIT registered itself with name binding protocol and it also had it's own DDP socket listener. My cdev could have set the selfsend flag, found any entity of the correct type on the local node and sent a ddp packet to this socket. After this the two programs can communicate by sharing memory. There are some problems with writing socket listeners under multifinder or using them from INITs. While writing a VBL task to control the sound driver, I came up with a pretty good solution that works just as well for socket listeners. The solution is LSC specific, since it uses the inline assembler. Here are some code fragments to get you started: /* Note: VVars is just any structure you need >> If A5 points to a VVars structure, the following macro will become >> xx(A5), where xx is the offset into that structure element. */ #define VBV(field) ((int) &((VVars *) 0)->field)(A5) VVars Vv; /* Vertical blanking variables */ /* >> Setup vertical blanking variables & >> install vertical blanking task. */ void InstallMyVBL() { long vbltask; asm { lea @myvbltask,A0 ;Get address of vbltask move.l A0,vbltask ;Store in local variable lea @mybase,A0 ;Get addr of variable base storage lea Vv,A1 ;Get addr of Vv record move.l A1,(A0) ;Store base in base storage } Vv.VBL.qType=vType; /* Vertical blanking queue. */ Vv.VBL.vblAddr=(ProcPtr)vbltask;/* Address of task */ Vv.VBL.vblCount=1; /* Every 1/60 seconds */ Vv.VBL.vblPhase=0; /* 0 is ok.. */ VInstall(&Vv.VBL); /* Install task in queue */ if(0) /* Skip the following :-) */ asm { @myvbltask move.l A5,-(SP) ;Save A5 move.l @mybase,A5 ;Get Vv address into A5 move.w #1,VBV(VBL.vblCount) ;Call again in 1/60 seconds [ Some code deleted... Vv structure elements are accessed as: sub.w #1,VBV(CountB) ;Decrement channel B count In C you would have written Vv.CountB ] @endvbl move.l (SP)+,A5 ;Restore A5 rts ;Return from vbl routine @mybase dc.l 0 ;Vv record address stored here. } } To install the VBL task, you call this routine and to control what it does you just change its variables. (Remember that this is "multitasking" so that you have to use some sort of locking to prevent the vbl task from seeing changes that aren't complete.) -- _._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._ | Juri Munkki jmunkki@hut.fi jmunkki@fingate.bitnet I Want Ne | | Helsinki University of Technology Computing Centre My Own XT | ~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~