From: pottier@clipper.ens.fr (Francois Pottier) Subject: C.S.M.P. Digest, Issue 3.006 Date: Fri, 18 Mar 94 16:15:51 MET C.S.M.P. Digest Fri, 18 Mar 94 Volume 3 : Issue 6 Today's Topics: 68K emulation and PPC toolbox questions. AE coercion handlers ? ARGH!!! Whamwhamwham!! (DialogSelect stuff) An offering: Assembly language code for a high speed copybits Animation speed: here we go again... Animation speed: improvement! Animation speed: more info Animation: the story continues... Blank Screen? C code for scrollable application help Can C be as fast as Assembler? (next...on the McLaughlin Group) Color Terminal Emulator DrawString + Ellipsis character ? Finder comments on non-Desktop DB volumes? Finding System Folder (Again) Free code: Sean's window manager How does the Finder handle events? How to determine color of progress bar? How to draw inits icons? How to tell a Mac from a Mac? I know the Mac MM isn't reentrant, but: If you use SysBeep() for debugging... Improving DrawText speed (Was: Color Terminal Emulator) Interface guidelines for extra program files Intermixing graphics and text Let's kill 24-bit mode! (was Re: Let's kill System 6!) Let's kill system 6! Never beep when using GWorlds. System software bug! PPC & 68k UPP problems PPC binaries Passing data through to completion procs? Password editing item.. Tricky? Permanent front windows... Preference file question! Reading PICT files != 72 dpi. How ? Resources on PowerPC Safer Segments ? Speeding up animation; questions System Folder on NONstartup disk Trap dispatcher overhead User in a menu? What happens if my Vertical Retrace task takes too long? When to StripAddress? (was Re: Let's kill 24-bit mode!) Why can't I have AEs *in* AEs? Why use handles at all, though? Writing To Screen Memory dirIDs jGNEFilter Q password encryption The Comp.Sys.Mac.Programmer Digest is moderated by Francois Pottier (pottier@clipper.ens.fr). 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. If you don't have access to news, you may still be able to post messages to the group by using a mail server like anon.penet.fi (mail help@anon.penet.fi for more information). 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 nef.ens.fr). Article threads are not added to the digest until the last article added to the thread is at least two weeks 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 digest is officially distributed by two means, by email and ftp. If you want to receive the digest by mail, send email to listserv@ens.fr with no subject and one of the following commands as body: help Sends you a summary of commands subscribe csmp-digest Your Name Adds you to the mailing list signoff csmp-digest Removes you from the list Once you have subscribed, you will automatically receive each new issue as it is created. The official ftp info is //ftp.dartmouth.edu/pub/csmp-digest. Questions related to the ftp site should be directed to scott.silver@dartmouth.edu. Currently no previous volumes of the CSMP digest are available there. Also, the digests are available to WAIS users as comp.sys.mac.programmer.src. ------------------------------------------------------- >From herman@ece.cmu.edu (Herman Schmit) Subject: 68K emulation and PPC toolbox questions. Date: 16 Mar 1994 19:32:32 GMT Organization: Electrical and Computer Engineering, Carnegie Mellon When doing 68K emulation, will a Power Mac do emulation of 68K toolbox routines, or does the emulator detect those routines and execute the PowerPC toolbox code for that routine? I'm also curious exactly why there will not be a 68K->PowerPC machine code translator in addition to an emulator. I always thought that the problem with translating between CPUs was not caused by different instruction sets but by different system/OS calls and different memory models. If the toolbox will be the same, the system/OS calls are no longer a problem. Do the Power Macs have a significantly different memory model? Even if they have a different memory model, couldn't you do some sort of emulation of the 68K memory and translate the everything else into PPC native code? Or is this what is done? herman +++++++++++++++++++++++++++ >From rang@winternet.mpls.mn.us (Anton Rang) Date: 17 Mar 1994 05:13:49 GMT Organization: Minnesota Angsters In article <2m7msg$s9f@fs7.ece.cmu.edu> herman@ece.cmu.edu (Herman Schmit) writes: >When doing 68K emulation, will a Power Mac do emulation of 68K toolbox >routines, or does the emulator detect those routines and execute the >PowerPC toolbox code for that routine? The emulator detects A-traps and dispatches them through the trap table, as happens on 68K machines. If the trap is written in PowerPC code, the Mixed Mode Manager switches to PowerPC native mode (if needed) and then runs it. Similarly, if the trap is in 68K code, the MMM switches to 68K emulation and then runs it. >I'm also curious exactly why there will not be a 68K->PowerPC machine >code translator in addition to an emulator. I always thought that the >problem with translating between CPUs was not caused by different >instruction sets but by different system/OS calls and different memory >models. First, there is at least one third-party translator available, FlashPort by Echo Logic. But it requires some input from the developers to do a good job; you can't just drag-and-drop onto it. Second, both problems exist. It's not trivial to convert between different code models *and get reasonable performance*. It can be done -- VEST on DEC's Alpha VMS machines is truly incredible! -- but it's very state-of-the-art and probably would have cost Apple many millions to develop.... -- Anton Rang (rang@winternet.mpls.mn.us) +++++++++++++++++++++++++++ >From zstern@adobe.com (Zalman Stern) Date: Fri, 18 Mar 1994 11:55:45 GMT Organization: Adobe Systems Incorporated Anton Rang writes > In article <2m7msg$s9f@fs7.ece.cmu.edu> herman@ece.cmu.edu (Herman Schmit) writes: > >When doing 68K emulation, will a Power Mac do emulation of 68K toolbox > >routines, or does the emulator detect those routines and execute the > >PowerPC toolbox code for that routine? > > The emulator detects A-traps and dispatches them through the trap > table, as happens on 68K machines. If the trap is written in PowerPC > code, the Mixed Mode Manager switches to PowerPC native mode (if > needed) and then runs it. Similarly, if the trap is in 68K code, the > MMM switches to 68K emulation and then runs it. In addition, some traps are "fat" and provide both 68K and PowerPC code. This avoids the overhead of a mixed-mode switch for very small routines. (Like say SetPort and GetPort.) All of the above applies to any routine descriptor, not just the ones placed in the trap table. The most common use is for callbacks passed to toolbox routines, however they can be used within your own code as well. (There is special support in Mixed Mode to handle the dispatching and calling conventions of traps of course.) -- Zalman Stern zalman@adobe.com (415) 962 3824 Adobe Systems, 1585 Charleston Rd., POB 7900, Mountain View, CA 94039-7900 "Do right, and risk consequences." Motto of Sam Houston (via Molly Ivins) --------------------------- >From paulr@syma.sussex.ac.uk (Paul Russell) Subject: AE coercion handlers ? Date: Wed, 2 Mar 1994 16:31:54 GMT Organization: University of Sussex Am I right in thinking that there are no default system AE coercion handlers ? Not even for such basic conversions as typeChar<->typeExtended ? Is there a utility for displaying the installed coercion handlers ? Are there any available handlers for common types, either as source or as an extension ? //Paul -- | Paul Russell | Internet: P.T.Russell@sussex.ac.uk | | Experimental Psychology | AppleLink: EP.SUSSEX | | Sussex University, Falmer | Telephone: +44 273 678639 | | Brighton BN1 9QG, England | Facsimile: +44 273 678433 | +++++++++++++++++++++++++++ >From jwbaxter@olympus.net (John W. Baxter) Date: Wed, 02 Mar 1994 12:43:30 -0800 Organization: Internet for the Olympic Peninsula In article <1994Mar2.163154.19747@syma.sussex.ac.uk>, paulr@syma.sussex.ac.uk (Paul Russell) wrote: > Am I right in thinking that there are no default > system AE coercion handlers ? Not even for such > basic conversions as typeChar<->typeExtended ? There are a bunch of coercions built in to the Apple Event Manager. As it happens, typeChar<->typeExtended is one of them. They are listed in Inside Mac: IAC in table 4-1, which occupies ALL of pages 4-43 and 4-44. There are more "exotic" ones built in, too, such as typeAppleEvent --> typeAppParameters (by far the easiest way to build THAT monster). > Is there a utility for displaying the installed > coercion handlers ? Yes...there is a little FKey. It puts up a nice list of all the Application handlers (event, coercion, object extraction, etc) for the front application, and all the System handlers. It is broken when the current Finder is in front [if it hurts, don't do it]. It's on the Developer CDs...since it is there, I don't know where else it may be. It can also be used to trigger the handlers, although I haven't exercised that ability. > Are there any available handlers for common > types, either as source or as an extension ? AppleScript installs a whole bunch more. And they are multiplying on the net. They can get pretty much as outrageous as you may want. I suppose a hypothetical typeRTF -> hypothetical typePostScript would be possible (but not written by me). -- John Baxter Port Ludlow, WA, USA [West shore, Puget Sound] jwbaxter@pt.olympus.net +++++++++++++++++++++++++++ >From paulr@syma.sussex.ac.uk (Paul Russell) Date: Thu, 3 Mar 1994 13:49:08 GMT Organization: University of Sussex John W. Baxter (jwbaxter@olympus.net) wrote: : In article <1994Mar2.163154.19747@syma.sussex.ac.uk>, : paulr@syma.sussex.ac.uk (Paul Russell) wrote: : > Am I right in thinking that there are no default : > system AE coercion handlers ? Not even for such : > basic conversions as typeChar<->typeExtended ? : There are a bunch of coercions built in to the Apple Event Manager. As it : happens, typeChar<->typeExtended is one of them. They are listed in Inside : Mac: IAC in table 4-1, which occupies ALL of pages 4-43 and 4-44. : There are more "exotic" ones built in, too, such as typeAppleEvent --> : typeAppParameters (by far the easiest way to build THAT monster). Thanks for the above and the rest of your comments - it looks like I have some sort of problem. I tried writing a small program which just calls AEGetCoercionHandler for a few different types and I get a -1717 for everything I've tried. I have Apple Event Manager 1.0.1 and AppleScript 1.0 installed and am running System 7.1. I think both Apple Event Manager 1.0.1 and AppleScript 1.0 may be out of date by now so I'll have a dig through the developer CD's and see if I can find something newer. //Paul -- | Paul Russell | Internet: P.T.Russell@sussex.ac.uk | | Experimental Psychology | AppleLink: EP.SUSSEX | | Sussex University, Falmer | Telephone: +44 273 678639 | | Brighton BN1 9QG, England | Facsimile: +44 273 678433 | +++++++++++++++++++++++++++ >From isis@netcom.com (Mike Cohen) Date: Thu, 3 Mar 1994 01:48:50 GMT Organization: ISIS International paulr@syma.sussex.ac.uk (Paul Russell) writes: >Am I right in thinking that there are no default >system AE coercion handlers ? Not even for such >basic conversions as typeChar<->typeExtended ? >Is there a utility for displaying the installed >coercion handlers ? >Are there any available handlers for common >types, either as source or as an extension ? >//Paul There are default handlers for most numeric types to/from text and from alias to FSSpec. With AppleScript installed, there are many more coercion handlers available. -- Mike Cohen - isis@netcom.com NewtonMail: MikeC49506 / ALink: D6734 / AOL: MikeC20 +++++++++++++++++++++++++++ >From paulr@syma.sussex.ac.uk (Paul Russell) Date: Fri, 4 Mar 1994 13:20:57 GMT Organization: University of Sussex Mike Cohen (isis@netcom.com) wrote: : paulr@syma.sussex.ac.uk (Paul Russell) writes: : >Am I right in thinking that there are no default : >system AE coercion handlers ? Not even for such : >basic conversions as typeChar<->typeExtended ? : >Is there a utility for displaying the installed : >coercion handlers ? : >Are there any available handlers for common : >types, either as source or as an extension ? : >//Paul : There are default handlers for most numeric types to/from text and from : alias to FSSpec. With AppleScript installed, there are many more coercion : handlers available. Thanks - I found the FKEY that displays the installed handlers and although there is a motley assortment of coercion handlers, none of the expected handlers for text<->float etc seem to be available. This appears to be the case on several Macs that I have tried this on, and I have also written a test program which calls AEGetCoercionHandler which returns -1717 for just about any pair of types I try. My best guess is that this is something to do with localisation - I am wondering if the US version of the Apple Event Manager/Apple Script checks the system version and doesn't install any handlers which might be country-specific ? If the above is not the correct explanation then I'd be interested to hear any other possible explanations for why the usual handlers aren't available ? //Paul -- | Paul Russell | Internet: P.T.Russell@sussex.ac.uk | | Experimental Psychology | AppleLink: EP.SUSSEX | | Sussex University, Falmer | Telephone: +44 273 678639 | | Brighton BN1 9QG, England | Facsimile: +44 273 678433 | +++++++++++++++++++++++++++ >From lai@apple.com (Ed Lai) Date: 4 Mar 1994 23:32:40 GMT Organization: Apple In article <1994Mar4.132057.18343@syma.sussex.ac.uk>, paulr@syma.sussex.ac.uk (Paul Russell) wrote: > Mike Cohen (isis@netcom.com) wrote: > : paulr@syma.sussex.ac.uk (Paul Russell) writes: > > : >Am I right in thinking that there are no default > : >system AE coercion handlers ? Not even for such > : >basic conversions as typeChar<->typeExtended ? > > : >Is there a utility for displaying the installed > : >coercion handlers ? > > : >Are there any available handlers for common > : >types, either as source or as an extension ? > > : >//Paul > > : There are default handlers for most numeric types to/from text and from > : alias to FSSpec. With AppleScript installed, there are many more coercion > : handlers available. > > Thanks - I found the FKEY that displays the installed handlers and > although there is a motley assortment of coercion handlers, none > of the expected handlers for text<->float etc seem to be available. > This appears to be the case on several Macs that I have tried this on, > and I have also written a test program which calls AEGetCoercionHandler > which returns -1717 for just about any pair of types I try. > > My best guess is that this is something to do with localisation - I am > wondering if the US version of the Apple Event Manager/Apple Script > checks the system version and doesn't install any handlers which might > be country-specific ? > > If the above is not the correct explanation then I'd be interested to > hear any other possible explanations for why the usual handlers aren't > available ? > > //Paul > > -- > | Paul Russell | Internet: P.T.Russell@sussex.ac.uk | > | Experimental Psychology | AppleLink: EP.SUSSEX | > | Sussex University, Falmer | Telephone: +44 273 678639 | > | Brighton BN1 9QG, England | Facsimile: +44 273 678433 | The FKEY displays the installed handlers, i.e. those handler installed using AEInstallXXX, but not the built-in handlers. The built-in handlers are listed in IM. The are built-in typeChar<->numericTypes. However they are not localized and are not meant for formating of numbers, they are more like what you expect to see in a debugger. -- /* Disclaimer: All statments and opinions expressed are my own */ /* Edmund K. Lai */ /* Apple Computer, MS303-3A */ /* 20525 Mariani Ave, */ /* Cupertino, CA 95014 */ /* (408)974-6272 */ zW@h9cOi +++++++++++++++++++++++++++ >From ldo@waikato.ac.nz (Lawrence D'Oliveiro, Waikato University) Date: 9 Mar 94 11:59:29 +1300 Organization: University of Waikato, Hamilton, New Zealand In article , isis@netcom.com (Mike Cohen) writes: > paulr@syma.sussex.ac.uk (Paul Russell) writes: > >>Am I right in thinking that there are no default >>system AE coercion handlers ? Not even for such >>basic conversions as typeChar<->typeExtended ? > > There are default handlers for most numeric types to/from text and from > alias to FSSpec. With AppleScript installed, there are many more coercion > handlers available. But one obvious one is missing: converting a pathname string to an alias or an FSSpec. I _always_ keep forgetting to prefix my pathnames with "file" or "alias"... Lawrence D'Oliveiro fone: +64-7-856-2889 Info & Tech Services Division fax: +64-7-838-4066 University of Waikato electric mail: ldo@waikato.ac.nz Hamilton, New Zealand 37^ 47' 26" S, 175^ 19' 7" E, GMT+13:00 +++++++++++++++++++++++++++ >From lai@apple.com (Ed Lai) Date: 10 Mar 1994 17:57:10 GMT Organization: Apple In article <1994Mar3.134908.28390@syma.sussex.ac.uk>, paulr@syma.sussex.ac.uk (Paul Russell) wrote: > John W. Baxter (jwbaxter@olympus.net) wrote: > : In article <1994Mar2.163154.19747@syma.sussex.ac.uk>, > : paulr@syma.sussex.ac.uk (Paul Russell) wrote: > > : > Am I right in thinking that there are no default > : > system AE coercion handlers ? Not even for such > : > basic conversions as typeChar<->typeExtended ? > > : There are a bunch of coercions built in to the Apple Event Manager. As it > : happens, typeChar<->typeExtended is one of them. They are listed in Inside > : Mac: IAC in table 4-1, which occupies ALL of pages 4-43 and 4-44. > > : There are more "exotic" ones built in, too, such as typeAppleEvent --> > : typeAppParameters (by far the easiest way to build THAT monster). > > Thanks for the above and the rest of your comments - it looks like I > have some sort of problem. I tried writing a small program which just > calls AEGetCoercionHandler for a few different types and I get a -1717 > for everything I've tried. I have Apple Event Manager 1.0.1 and > AppleScript 1.0 installed and am running System 7.1. I think both > Apple Event Manager 1.0.1 and AppleScript 1.0 may be out of date > by now so I'll have a dig through the developer CD's and see if > I can find something newer. > > //Paul > -- > | Paul Russell | Internet: P.T.Russell@sussex.ac.uk | > | Experimental Psychology | AppleLink: EP.SUSSEX | > | Sussex University, Falmer | Telephone: +44 273 678639 | > | Brighton BN1 9QG, England | Facsimile: +44 273 678433 | AEGetCoercionHandler just returns whether an XXXX->YYYY coercion handler has been installed, it does not really tell you if a particular coercion exists. Built-in handler does not have a fixed address since the PACK can be relocated so the address cannot be returned. And if XXXX->YYYY coercion is handled by the ****->YYYY coercion handler, AEM has no idea that XXXX->YYYY can or cannot be done through ****->YYYY. So the rule is that it strictly returns an XXXX->YYYY address if it exists, it is not meant to rule out the existence of the possibility of XXXX->YYYY coercion. -- /* Disclaimer: All statments and opinions expressed are my own */ /* Edmund K. Lai */ /* Apple Computer, MS303-3A */ /* 20525 Mariani Ave, */ /* Cupertino, CA 95014 */ /* (408)974-6272 */ zW@h9cOi +++++++++++++++++++++++++++ >From jonpugh@netcom.com (Jon Pugh) Date: Sat, 12 Mar 1994 07:19:44 GMT Organization: NETCOM On-line Communication Services (408 241-9760 guest) Lawrence D'Oliveiro, Waikato University (ldo@waikato.ac.nz) wrote: > But one obvious one is missing: converting a pathname string to an alias or > an FSSpec. I _always_ keep forgetting to prefix my pathnames with "file" or > "alias"... This is done and working as part of Jon's Commands 1.1. Interested in beta testing? Jon --------------------------- >From gjw2824@hertz.njit.edu (Greg Weston) Subject: ARGH!!! Whamwhamwham!! (DialogSelect stuff) Date: 5 Mar 94 19:58:17 GMT Organization: New Jersey Institute of Technology, Newark, New Jersey Howdy, folks. I've been playing with everyone's favorite UI addition: Floating Windows. I've gotten them to work smoothly and cleanly, and they interact fine with normal windows and dialogs (modal or not). The only problem is within a pair of cute little routines called IsDialogEvent and DialogSelect. They don't like having a (floating) window in front of the Dialog they're working with. So, I re-wrote them. (Cough. Embarrased grin.) Still no problem. I'm left with one teensy little problem: How in the blazes does DialogSelect do its magic when you have multiple editTexts in a dialog and either click in a non-current one or press Tab?!?! On that topic, IM is silent, and I can't figure out how to successfully pull off the swap with what they give you. Any thoughts, suggestions, or even polite chuckles would be appreciated. Thanks, Greg +++++++++++++++++++++++++++ >From cconstan@epdiv1.env.gov.bc.ca (Carl B. Constantine) Date: Mon, 07 Mar 1994 10:31:52 -0800 Organization: Ministry of Environment, Lands & Parks In article <1994Mar5.195817.28298@njitgw.njit.edu>, gjw2824@hertz.njit.edu (Greg Weston) wrote: > Howdy, folks. I've been playing with everyone's favorite UI addition: > Floating Windows. I've gotten them to work smoothly and cleanly, and > they interact fine with normal windows and dialogs (modal or not). The > only problem is within a pair of cute little routines called > IsDialogEvent and DialogSelect. They don't like having a (floating) > window in front of the Dialog they're working with. > > So, I re-wrote them. (Cough. Embarrased grin.) Still no problem. I'm > left with one teensy little problem: > How in the blazes does DialogSelect do its magic when you have > multiple editTexts in a dialog and either click in a non-current one > or press Tab?!?! > > On that topic, IM is silent, and I can't figure out how to > successfully pull off the swap with what they give you. Any thoughts, > suggestions, or even polite chuckles would be appreciated. > Thanks, > Greg One solution the new IM suggests instead of using dialog Select, you can use a custom routing to take a look at what kind of window the event occured in and then process the event that way. Very usefull if you're dealing with modeless and movableModal Dialogs. Source: IM Macintosh Toolbox Essentials, ch. 6 Dialog Manager. -- ========================================================================= Carl B. Constantine B.C. Environment, Lands & Parks End-User Support Analyst CCONSTAN@epdiv1.env.gov.bc.ca +++++++++++++++++++++++++++ >From Steve Bryan Date: Tue, 8 Mar 1994 15:37:06 GMT Organization: Sexton Software In article <1994Mar5.195817.28298@njitgw.njit.edu> Greg Weston, gjw2824@hertz.njit.edu writes: >How in the blazes does DialogSelect do its magic when you have >multiple editTexts in a dialog and either click in a non-current one >or press Tab?!?! I can't tell exactly how far along you are in this project but if you haven't taken a look at the DialogRecord structure you should do so now (I know, you probably have). DialogRecord = record window: WindowRecord; items: Handle; textH: TEHandle; editField: Integer; editOpen: Integer; aDefItem: Integer; end; You need to manipulate the textH and editField variables. EditField points to the current text item in the linked list starting at items. Of course you have to update the current text item before setting up textH for the new text item. I thought there was some fairly useful information about this stuff in Inside Mac Volume I. My volume I is at home so I can't check but try looking there. +++++++++++++++++++++++++++ >From u9119523@sys.uea.ac.uk (Graham Cox) Date: Wed, 9 Mar 1994 17:01:47 GMT Organization: School of Information Systems, UEA, Norwich In article , cconstan@epdiv1.env.gov.bc.ca (Carl B. Constantine) wrote: > In article <1994Mar5.195817.28298@njitgw.njit.edu>, gjw2824@hertz.njit.edu > (Greg Weston) wrote: > > > Howdy, folks. I've been playing with everyone's favorite UI addition: > > Floating Windows. I've gotten them to work smoothly and cleanly, and > > they interact fine with normal windows and dialogs (modal or not). The > > only problem is within a pair of cute little routines called > > IsDialogEvent and DialogSelect. They don't like having a (floating) > > window in front of the Dialog they're working with. > > > > So, I re-wrote them. (Cough. Embarrased grin.) Still no problem. I'm > > left with one teensy little problem: > > How in the blazes does DialogSelect do its magic when you have > > multiple editTexts in a dialog and either click in a non-current one > > or press Tab?!?! > > [SNIP!] If your question is how does it switch from one field to another, then I can answer! In the DIALOGRECORD is a field which contains the ID number of the current editable item. When you hit tab, this is incremented and GetDItem called to see if the resulting item is an edit field, if not, it increments until it finds one or until the last item is found, at which point it starts over from item 1. When it finds an edit field item, it retrieves the text from the current one and stashes it into the item list as that item's string, then installs the text from the new one into the teRecord using TESetText, then selects it with TESetSelect, or if it was a click, calls TEClick. The DialogRecord also contains the teHandle. The DialogRecord itself is documented in IM, though this sequence of events isn't- I had to figure this out for myself once when trying to do something along the same lines as you. You can get the dialog record by casting the DialogPtr to type DialogPeek. Hope this helps! > ========================================================================= > Carl B. Constantine B.C. Environment, Lands & Parks > End-User Support Analyst CCONSTAN@epdiv1.env.gov.bc.ca - ------------------------------------------------------------------------ Love & BSWK, Graham -Everyone is entitled to their opinion, no matter how wrong they may be... - ------------------------------------------------------------------------ - ------------------------------------------------------------------------ Love & BSWK, Graham -Everyone is entitled to their opinion, no matter how wrong they may be... - ------------------------------------------------------------------------ +++++++++++++++++++++++++++ >From qsi@NU91.wlink.nl (Peter Kocourek) Date: Tue, 08 Mar 1994 20:55:13 +0100 Organization: (none) Greg Weston wrote in a message on 05 Mar 94 to All GW> Howdy, folks. I've been playing with everyone's favorite UI GW> addition: Floating Windows. I've gotten them to work smoothly GW> and cleanly, and they interact fine with normal windows and GW> dialogs (modal or not). The only problem is within a pair of GW> cute little routines called IsDialogEvent and DialogSelect. GW> They don't like having a (floating) window in front of the GW> Dialog they're working with. GW> So, I re-wrote them. (Cough. Embarrased grin.) Still no problem. I'm GW> left with one teensy little problem: How in the blazes does GW> DialogSelect do its magic when you have multiple editTexts in a GW> dialog and either click in a non-current one or press Tab?!?! These two issues are separate from one another. Handling Tab presses is far easier than getting the mouseclick-induced editText change right. In fact, I haven't been able to get my own routines to do this properly. I was writing my own replacements for DialogSelect (to handle movable modals and modeless dialogs, with enhancements) and bumped into this problem. I tried all sorts of things with the TERecord, but I wasn't able to get the swap done cleanly. So I cheated. :-) In my generic mouseDown-handling procedure (within my DialogSelect replacement), I first check to see where the mouseDown occurred. If it is in an editText field, I check whether it's the currently active text-input-capable [TIC, my shorthand] item, and in that case a simple TEClick call will take care of everything. If it is not the active TIC item (you have to keep track of this separately), and the currently active TIC is not an editText item, I call the deactivate function for the TIC; this is usually a custom routine for userItems which contain lists, for instance. One aesthetic problem with this is, that userItems don't have refCons, so that storing the ProcPtr's for userItem service routines is a bit cumbersome. Anyway, once your previously active TIC item is deactivated, you can activate manually the TERecord, and call TEClick. If, however, the active TIC item is an editText item, you'll have to "cheat". Having found no way doing the transition from one editText item to another cleanly, I simply call the real DialogSelect at that point. Note that I only do this when I have determined unambiguously, that the action to be taken is switching from one editText item to anohter. As for handling Tabs, the situation is a bit easier. You have to find the next TIC item in your dialog (or the previous one, if the user pressed shift-Tab), and handle the deactivating and activating as above. The one thing that makes it doable without "cheating", is that you don't have to place the caret anywhere within the text of the next editText item (this was causing my problems), but you either select the entire text, if there is any, or you place just a caret, if there isn't. I'll include my source code where I do this. Parts of the code are specific to my implementation. For instance, I store a struct via a Handle in the window refCon. This struct contains lots of information about the dialog; you'll have to adapt it to your own needs. You will have to provide the CanAcceptText and ActivateItem functions for your own userItems. (sorry about the formatting) /************************************************************************************* * Somehow I'm not sure I should be doing this... requires too much thinking. * CycleKeyBoardInput is a generic routine that will find and activate the next (or * previous) item in the DITL that can accept keyDown events. To do this, it needs: * + a DialogPtr, to indicate in which dialog to look, and to get at the WIHandle. * + a Boolean isShiftPressed, to determine whether to search forward or backward in * the DITL * + a pointer to a function, that returns a Boolean. If this function, CanAcceptText, * returns TRUE, then the userItem (passed as a short to CanAcceptText) can accept * keyDown events. This function should be declared along with the other specific * functions for this dialog (as in AddressesDialog.c) * + another pointer to a function, that will either activate or deactivate a userItem * in the DITL, that can accept text. {De}Activating editText items is done here. * ************************************************************************************/ void CycleKeyboardInput(DialogPtr dPtr, Boolean isShiftPressed, Boolean (*CanAcceptText)(short), void (*ActivateItem)(WindowInfoHandle, short, Boolean)) { WindowInfoHandle aWIHandle; /* my own struct with info */ short numItems, activeItem, queryItem, iType; aWIHandle = (WindowInfoHandle)GetWRefCon(dPtr); activeItem = (**aWIHandle).activeItem; /* keeping track of the active TIC */ queryItem = activeItem + (isShiftPressed ? -1 : 1); numItems = CountDITL(dPtr); while (queryItem != activeItem) /* check to see if we're back where we started */ { if (queryItem == 0) /* handle rollover */ queryItem = numItems; else if (queryItem == numItems+1) queryItem = 1; GetDItem(dPtr, queryItem, &iType, &workHandle, &workRect); /* get item info */ if (iType == editText) /* if editText, we're finished */ break; if (iType == userItem && CanAcceptText(queryItem)) /* same for userItem */ break; isShiftPressed ? queryItem-- : queryItem++; /* get next item to query */ } if (queryItem != activeItem) /* found a new one? */ { short aType; GetDItem(dPtr, activeItem, &aType, &workHandle, &workRect); if (aType == userItem) ActivateItem(aWIHandle, activeItem, FALSE); /* deactivate currently active user item */ if (iType == editText) { SelIText(dPtr, queryItem, 0, 32767); /* select new editText item */ workTEHandle = ((DialogPeek)dPtr)->textH; } else if (iType == userItem) { if (aType == editText) /* was previously active item an editText? */ TEDeactivate(((DialogPeek)dPtr)->textH); ActivateItem(aWIHandle, queryItem, TRUE); /* select new userItem */ workTEHandle = NIL; } (**aWIHandle).activeItem = queryItem; UpdateEditMenus(workTEHandle, kSystemTE); /* my own service proc */ } } I hope you can make some sense out of all this. :-) Additional notes: CountDITL is System 7 specific (may come with CTB under System 6), but I don't do System 6 anymore. An example of an ActivateItem function would be for a list to draw a border around the list, to alert the user that keypresses will go to the list (to select a cell in the list). GW> On that topic, IM is silent, and I can't figure out how to GW> successfully pull off the swap with what they give you. Any GW> thoughts, suggestions, or even polite chuckles would be appreciated. :-) YHS:QSI! +++++++++++++++++++++++++++ >From gjw2824@hertz.njit.edu (Greg Weston) Date: 10 Mar 94 20:38:09 GMT Organization: New Jersey Institute of Technology, Newark, New Jersey Well, I had three people respond, each with different suggestions, and got it working with the first one. I'd like to thank Steve Bryan, Carl Constantine, and Simon Ward for their advice. I had looked through the IM vol 1 stuff pretty carefully, but the mechanics of the manipulation really were sketchy. My NIM is 100+ miles away, so I didn't have that to look through. I have a solution that works quite well, though, and I'm very happy with the finished product. Thank you kindly, and y'all will probably see a submission to the standard archives soon. Greg --------------------------- >From ejohnson@netcom.com (Eric Johnson) Subject: An offering: Assembly language code for a high speed copybits Date: Fri, 18 Mar 1994 07:50:48 GMT Organization: NETCOM On-line Communication Services (408 241-9760 guest) About two weeks ago, I had mentioned that I had written some assembly language code that could beat copybits given certain assumptions. A number of people (Alex Metcalf and David Wareing) had asked me to send them some samples. I was going to write up some demo code with it, but never got around to it due to work obligations. A few days ago, I sent David an email message with some and a length explanation. I figured that maybe everyone else could benefit from the email to. Keep in mind that the following code was my first real whack at some high speed copybits. I may be breaking a few rules, or doing bad Mac programmer things. So USE IT AT YOUR OWN RISK. I believe further enhancements can be made to it, especially given the wide spread prominence of the 030 and 040. When I first wrote it, the 020 was in much more common use. This code has evolved into a copybits that will do some very fast masking. I had used it for a graphics engine that would display things at a perspective. Where each icon was a perspective block, if you will. Thus masking was needed. It looks quite sharp. I can go over that code too, as well as the trick I put in for some fast masking. As always, you pay for the speed. It needs a bit of memory. Let me know if this helps anyone. Here is the message I sent to David Wareing. <-------------> David, Okay, here's some code with some explanation off the top of my head. This code was developed for a tile based adventure game that was never quite finished. The graphics were a simple display consisting of 11x11 icons where each icon was a 24x24 cicn resource. This type of display is identical to that of the old Ultima games on the Apple ][ and old PC's. And the more recent Zelda of Nintendo or Civilization on the Macintosh. I initially wrote everything in C, and used PlotCIcon to place my color icons on the screen. In found that to be too slow, because the Mac was constantly converting the colors in the resource to those available on the screen. Hence the molases like quality. So I said to myself, "Screw it, I'm going do it in assembly.". Even though the code I'm including has been rewritten for a slightly more complex display, I'm giving this to you so you can follow the history of its development. It should make more sense this way, and you'll see some room for improvements along the way. I wrote this as a beginner Mac programmer, so I may be breaking some rules. Let's first identify what slows down drawing to the screen. In my case, I had a few mistakes. The first one was using PlotCIcon. The Mac was constantly converting the resource into the current colors available in the port. That's all well and good, in fact that's quite nice of them. But it slows things down a bit. To get around this, I created an off screen window that would warehouse my icons. The benefit is that the off screen window would have the same color table [CLUT, right?] so any transfer between an offscreen window and the main screen would be a trivial copy. Thus, at start time, I painted each icon into the off screen to "coerce" it into the current system table. Okay, so I did that. I would then use copy bits to repaint my window. In my game, I have a two dimensional array with numbers indicating which icon goes at what location. So, I would get the id number of the display icon, locate it in my off screen window [the palette of icons] and use copybits to get it to the window. Well, that was better, but was still slower than I expected. So, I got to thinking about how to speed things up. The bottleneck in this case is copybits. Sure, copybits is fairly fast, but I know a few things about my icons that it doesn't know. They are all of the same width, and same height. But how do I put this knowledge to good use? Let's step back for a second and look at the Motorola architecture. When I wrote it, I decided to take advantage of the features found in the 68020's and later. It really starts to do well in the 030. We won't consider the 68000 because there's not much you can do for that chip. The 680x0 has 8 32 bit data registers and 8 32 address registers. You lose some of the address registers to the system, but all in all, there's some room to play around in. The 68020 and later have some code cache and data caches to work with too. In other words, you can have a loop fill up the instruction cache, and then the CPU can run faster because all of its code is in the cache. It's this instruction cacheing that I take full advatange of. In later developments of this code, I try to take advantage of the data cache. So, we need to write some assembly language code that will copy 24 bytes at a time from 24 different parts of memory. Remember, in this case, my icons are 24 bytes wide (24 pixels at 8 bits a pixel). And the are 24 pixels high. So, we've got 24 blocks of 24 pixels. Each block starts at a slightly different memory location. My code loops 24 times, one for each row of 24 bytes. Thus, the code that copies each row lands in the instruction cache. So, on each subsequent reitiration of the code, we are running strictly from the cache. This gives us some good performance. But there's one more feature too. Most modern processors have a pipeline where the different parts of the CPU execute part of an instruction then hand it off to the next step. It works identically to an assembly line where someone installs the engine and the next person installs the tires. A new car always rolls off the line every so often even though it may take a bit for a car to travel the entire line. The catch lies with branch instructions. The CPU won't know if the branch should be taken until its evaluation is complete. But, this means that the CPU won't necessarily be putting the right instructions in the pipeline. It would be like producing a car that indicated the previous cars should be destroyed. This wrecks efficiency. To get around it, Motorola has provided an instruction, dbra, that serves as a hint. dbra tells the CPU to branch if the contents of the data register are not zero. It instructs the CPU to expect the branch and fill the pipeline with the instructions that would result if a branch takes place. So, my loops gets two nice features going. The instruction cache and it keeps the pipeline going too. Pretty sweet, eh? My code works in two steps. The first section is the prepatory work for the loop. I put as much stuff as I can into registers, because adding and multiplying "in register" is much faster than from memory. And the instructions are shorter, which means less space is taken up in the instruction cache. This point of putting stuff "in register" may seem anal, but remember, we need to add some values at the end of each iteration of the loop and keeping stuff as fast and small is good. Now, let's go over the parameters to the code. mySource points to the start of the off screen palette. myDestination points to the start of the off screen drawing space. xSource and ySource are the x,y coordinates of the pixel that represents the upper left hand corner of the thing you wish copied. Keep in mind that these are *PIXEL COORIDINATES* not icon coordinates. Its up to you to find the start of the icon you wish copied in your off screen palette of icons. I suppose my code could do it. I just didn't bother. xDestination and yDestination are the same xSource and ySource except for the destination array. iconSize should be your icon height minues one. In my case, its 23. int MyCopyBits8(Ptr mySource, Ptr myDestination, long int xSource, long int ySource, long int xDestination, long int yDestination, long int iconSize) { asm 68000 { /** ** We need to save the registers that we are going to clobber. ** ** a1 starts out pointing to the top of the pallete, but it . ** will eventually end up pointing to the start of the source ** icon. Same goes for a2. ** ** d2 and d3 are a bit tricky to explain. They are the row ** byte values for the source and destination. A row byte ** value is the number of bytes required to jump down to the ** next row. It needs to be a multiple of four else some ** Mac internals complain. We use these values to find the ** real location of both icons. ** **/ movem.l a1-a2/d0-d3, -(sp); /* save the regs */ move.l mySource,a1; move.l myDestination,a2; move.l #0x0780,d2; /* hard coded row bytes value */ move.l #0x0138,d3; /* hard coded row bytes value */ /** ** The following four lines find the real address of the source ** icon. They do this by following a simple formula. ** real_source = base + y Position * row bytes for Src + x Pos ** This result is placed into a1 as mentioned before. **/ move.l ySource,d0; mulu d2,d0; add.l d0,a1; add.l xSource,a1; /** We follow the same formula for the destination address **/ move.l yDestination,d0; mulu d3,d0; add.l d0,a2; add.l xDestination,a2; /** ** The following will seem a bit weird. Why subtract #20 from the ** row byte values? Keep in mind that as we are copying from the ** source to the destination, we are changing our pointers ** (marching them across the icon). When we are finished copying, ** we need to add the rowBytes-20 to get to the first byte of the ** the next row. Note that 20 is iconSize-3. Yeah, that should be ** that way in the code. Just never bothered to change it. **/ sub.l #20,d2; sub.l #20,d3; move.l iconSize,d0; /** END OF PREPARTORY WORK **/ /** And now you're ready to start the copy of each row of bytes **/ @1 ; move.l (a1)+,(a2)+; /** Note that we are increasing our **/ move.l (a1)+,(a2)+; /** pointers as go along here. **/ move.l (a1)+,(a2)+; /** Also note that we copy four **/ move.l (a1)+,(a2)+; /** bytes at a crack. And we do it **/ move.l (a1)+,(a2)+; /** six times. For 24 bytes! **/ move.l (a1),(a2); add.l d2,a1; /** We need to jump down to the start of **/ add.l d3,a2; /** first pixel in the next row. **/ dbra d0,@1; /** Branch until we are done **/ movem.l (sp)+, a1-a2/d0-d3 /* restore the registers */ } return(1); } -- Eric E Johnson ejohnson@netcom.netcom.com --------------------------- >From alex@metcalf.demon.co.uk (Alex Metcalf) Subject: Animation speed: here we go again... Date: Sat, 12 Mar 1994 10:14:53 GMT Organization: Demon Internet Now that we've exhausted the previous "animation speed" thread, it's time to start another. :-) Having got my game code to run (what I considered to be) extremely fast on my LC475, I thought I'd give it a whirl on our IIsi. Oh no! Extremely slow animation speed. I know that the IIsi has very slow video, but what was running at 60fps on an LC475 surely wouldn't be reduced to less than 10fps on a IIsi. One of the things I thought might be causing the problem was that I still might be having problems matching colour tables between the GWorld and the window on-screen. I'm creating a normal colour window, and making it the size of the screen (0,0,640,480). I'm not changing its palette in any way. Then I'm using NewGWorld with a pixel depth of 0, which is meant to optimise CopyBits calls with the screen. It's also meant to use the colour table info and screen depth of the deepest monitor intercepting the given rectangle. Since I've only got one monitor, this shouldn't be the problem. However, response still seems to be unreasonbly sluggish on the IIsi: whether its in gray scale or colour, the speed is disappointing. I believe Andrew Welch (hope I spelt your name right) reads this area regularly: for Maelstrom, what is the animation speed like on low end '030 Macs? I know you use heavily optimised assembler for your animation, but I don't think that what I'm doing (CopyBits) should case such a dramatic difference in animation speed. Is there any way to make CopyBits completely ignore the colour table differences? Interesting ideas and suggestions are always appreciated. Alex -- Alex Metcalf, Mac programmer in C, C++, HyperTalk, assembler Internet, AOL, BIX: alex@metcalf.demon.co.uk AppleLink: alex@metcalf.demon.co.uk@internet# CompuServe: INTERNET:alex@metcalf.demon.co.uk Delphi: alex@metcalf.demon.co.uk@inet# FirstClass: alex@metcalf.demon.co.uk,Internet Fax (UK): (0570) 45636 Fax (US / Canada): 011 44 570 45636 +++++++++++++++++++++++++++ >From Arsenault_C@msm.cdx.mot.com (Chris Arsenault) Date: Tue, 15 Mar 1994 12:29:41 -0500 Organization: Motorola Codex In article , alex@metcalf.demon.co.uk (Alex Metcalf) wrote: > However, response still seems to be unreasonbly sluggish on the > IIsi: whether its in gray scale or colour, the speed is disappointing. It sounds like you're okay with your color tables and CopyBits. You might be running into a hardware problem. There is no separate VRAM for video on the IIsi (or IIci). The IIsi has 1 MB on the motherboard, a portion of which it uses as video RAM. Not that I've investigated this, but I remember reading that if the disk cache is boosted to occupy the majority of motherboard RAM, then the video driver uses the SIMMs instead and because the SIMM RAM doesn't have to deal with a bank switch wait you can get approx. a 30% speed increase. The unfortunate part about this is that it's not really software controllable - it's sort of up to the user. Chris -- #include --------------------------- >From alex@metcalf.demon.co.uk (Alex Metcalf) Subject: Animation speed: improvement! Date: Sun, 6 Mar 1994 23:16:59 GMT Organization: Demon Internet I discovered something quite interesting this afternoon, which has almost doubled the speed of the sprite animation in my game. Just a quick recap: my game copies the background (behind the sprites) to a gworld, copies the sprites the same gworld, and then copies that rectangle to the screen. In all, I was using 5 CopyBits for the background, 5 CopyMasks for the sprites, and 5 CopyBits for copying to the screen. Someone originally suggested that I combined all the rectangles into a region and do a single CopyBits call. However, it turned out to be slower! Go figure. I guess the individual CopyBits calls outstrip the RectRgn and UnionRgn calls. This afternoon, I thought I'd give it another shot, in case I'd missed something (or done a goofy error which was slowing things down). This time, for no particular reason, I chose to combine the rectangles for my CopyBits calls to the screen, and only do the single CopyBits call. I gave it a go and... WHOAH! Unbelievable speed increase (almost 200%, 60 fps). It seems that CopyBits calls have much more overhead when copying to the screen rather than copying between offscreen gworlds. I guess this is because it checks screen depth, colour tables, etc. etc. To give you an idea of the speed increase: with the extra "time" I had in my game loop, I was able to add another 4 sprites to the screen, resulting in another 4 CopyBits calls and 4 CopyMask calls. Even then, it was still faster than when I was using individual CopyBits calls to the screen! So, I've found that the fastest way (with normal QuickDraw routines) to make my animation work is to use individual CopyBits calls for sprites between GWorlds, and then a single CopyBits call when it's all ready to come to the screen. Here's my code snippet for the copy-to-screen, where gWorldRect is 0,0,640,480 (full screen). I guess I don't need the second SetEmptyRgn call. (I use "t" to denote local variables). // ------ SetEmptyRgn (tCopyRgn); SetEmptyRgn (tRectRgn); tObject = gFirstObject; while (tObject != nil) { if (!tObject->fVisible) { tObject = (GameObject) tObject->fNextObject; continue; } RectRgn (tRectRgn, &tObject->fAnimEnclosureRect); UnionRgn (tRectRgn, tCopyRgn, tCopyRgn); tObject = (GameObject) tObject->fNextObject; } CopyBits ((BitMap *) *tPixMap[3], (BitMap *) &gGameWindow->portPixMap, &gWorldRect, &gWorldRect, srcCopy, tCopyRgn); // ------ On a slightly different topic: thanks to some code by Francis (Francis H Schiffer 3rd), I was able to test my game loop to see where the time was being used up. I knew that the copying of graphics takes up quite a lot of time, but I'd never imagined that it tool 98% of the time! Needless to say, that is what inspired me to have another go at improving the CopyBits speed... Thanks again to all those who have given suggestions and code snippets.... they've all been very useful (or at least, interesting!). Alex -- Alex Metcalf, Mac programmer in C, C++, HyperTalk, assembler Internet, AOL, BIX: alex@metcalf.demon.co.uk AppleLink: alex@metcalf.demon.co.uk@internet# CompuServe: INTERNET:alex@metcalf.demon.co.uk Delphi: alex@metcalf.demon.co.uk@inet# FirstClass: alex@metcalf.demon.co.uk,Internet Fax (UK): (0570) 45636 Fax (US / Canada): 011 44 570 45636 +++++++++++++++++++++++++++ >From u9119523@sys.uea.ac.uk (Graham Cox) Date: Mon, 7 Mar 1994 11:23:35 GMT Organization: School of Information Systems, UEA, Norwich In article , alex@metcalf.demon.co.uk (Alex Metcalf) wrote: > > I discovered something quite interesting this afternoon, which has > almost doubled the speed of the sprite animation in my game. > [SNIP!] I also read somewhere that CopyBits with a mask region parameter is faster than CopyMask- you might want to try this and see if it's true. - ------------------------------------------------------------------------ Love & BSWK, Graham -Everyone is entitled to their opinion, no matter how wrong they may be... - ------------------------------------------------------------------------ +++++++++++++++++++++++++++ >From Tony Myles Date: 7 Mar 1994 21:45:34 GMT Organization: The 3DO Company In article Alex Metcalf, alex@metcalf.demon.co.uk writes: [stuff deleted] > So, I've found that the fastest way (with normal QuickDraw >routines) to make my animation work is to use individual CopyBits calls for >sprites between GWorlds, and then a single CopyBits call when it's all >ready to come to the screen. [stuff deleted] Hey, thats cool. Hmm, just out of curiosity, what kind of Mac are you running this on? I think I tried this a long time ago on a Q800, and it was still slower than individual CopyBits calls to the screen. I'll have to try it again though, I can't remember if I did it quite the way you describe. ...Tony - --------------------------------------------- Tony Myles work: tony.myles@3do.com The 3DO Company home: suiryu@aol.com +++++++++++++++++++++++++++ >From alex@metcalf.demon.co.uk (Alex Metcalf) Date: Tue, 8 Mar 1994 13:38:19 GMT Organization: Demon Internet In article <2lg79u$lp8@mac_serv.3do.COM>, Tony Myles wrote: > In article Alex Metcalf, > alex@metcalf.demon.co.uk writes: > [stuff deleted] > > So, I've found that the fastest way (with normal QuickDraw > >routines) to make my animation work is to use individual CopyBits calls > for > >sprites between GWorlds, and then a single CopyBits call when it's all > >ready to come to the screen. > [stuff deleted] > > > Hey, thats cool. Hmm, just out of curiosity, what kind of Mac are you > running this on? > I'm running this on an LC475. I believe I've got all the colour tables matched up correctly, and the source and destination rectangles are the same (and the bit depths). Alex -- Alex Metcalf, Mac programmer in C, C++, HyperTalk, assembler Internet, AOL, BIX: alex@metcalf.demon.co.uk AppleLink: alex@metcalf.demon.co.uk@internet# CompuServe: INTERNET:alex@metcalf.demon.co.uk Delphi: alex@metcalf.demon.co.uk@inet# FirstClass: alex@metcalf.demon.co.uk,Internet Fax (UK): (0570) 45636 Fax (US / Canada): 011 44 570 45636 --------------------------- >From alex@metcalf.demon.co.uk (Alex Metcalf) Subject: Animation speed: more info Date: Thu, 3 Mar 1994 00:25:29 GMT Organization: Demon Internet Thanks to those who sent replies to me about improving the animation speed in my game. I thought I'd be a little more specific in this description about exactly what I'm doing, and (as always) I appreciate any feedback. I have an arcade game which I would like to run at 30 fps on a 68030 Mac or better. It currently DOES run at 30 fps on my LC475, but only just, and since that's on a 68LC040, I don't stand much chance of 30 fps on an 030! In my game, there are 5 or 6 sprites always on the screen, each of them 24 x 24 pixels in size. There are a number of calculations that I do with them each time through my 2 tick "loop", but I'm assuming that I can get the most speed increase by improving my animation code. I have four (yeah, four) offscreen gworlds, three of them in 8 bit and 1 in 1 bit. I'll call the 1 bit one the "mask world", and the other ones worlds "one", "two", and "three". In world one, I have all my sprite animations, placed there from a PICT resource. In the mask world, I have the masks for the sprites, all with exactly the same rectangles as the ones in world one. In world two, I have the background. I'm using world 3 as the destination world for preparing to copy to the screen window. Every time through my loop, I first copy all the background rects to world three, each one covering the previous location and the next location of a sprite. This is done with a CopyBits call between worlds. Then, I use CopyMask to copy the sprites (from world one and the mask world) on to the background (world three). Finally, I copy each of the background rects onto the screen, again using CopyBits. So in summary: I make 6 CopyBits calls between worlds, 6 CopyMask calls between worlds, and 6 CopyBits calls from the world to the screen. The rectangles being copied are no more than 32 x 32. How can I speed this up? I know that assembly programming would be useful here, but hacking up an assembler copy between gworlds is a new project to me. I would like to get the animation up to a speed where I can do 30 fps on a 20mhz 68030, with slow screen redraw (a.k.a. our Mac IIsi). Thanks in advance for any help you can give me. Alex -- Alex Metcalf, Mac programmer in C, C++, HyperTalk, assembler Internet, AOL, BIX: alex@metcalf.demon.co.uk AppleLink: alex@metcalf.demon.co.uk@internet# CompuServe: INTERNET:alex@metcalf.demon.co.uk Delphi: alex@metcalf.demon.co.uk@inet# FirstClass: alex@metcalf.demon.co.uk,Internet Fax (UK): (0570) 45636 Fax (US / Canada): 011 44 570 45636 --------------------------- >From alex@metcalf.demon.co.uk (Alex Metcalf) Subject: Animation: the story continues... Date: Sun, 6 Mar 1994 00:45:45 GMT Organization: Demon Internet Just a quick update on my original question about speeding up animation in my game code. Thanks to all those who gave suggestions for speeding things up: I'm sorry I haven't had a chance to reply to each of you individually, but I've had a huge amount of email (about 50 messages a day) and I'm finding it hard to keep up. Along side this game, I'm working on about 5 or 6 different HyperCard external projects, and that mail (together with regular newsletters and listserv discussions) makes life quite busy! Anyway, here are a few of the suggestions I've tried: o A suggestion was made that rather than CopyBits each of the sprites from one world to another, I should combine them into a single region and make only one CopyBits call. Here's the way I was doing it before: ... tObject = gFirstObject; while (tObject != nil) { if (!tObject->fVisible) { tObject = (AppObject) tObject->fNextObject; continue; } CopyBits ((BitMap *) *tPixMap[2], (BitMap *) *tPixMap[3], &tObject->fAnimEnclosureRect, &tObject->fAnimEnclosureRect, srcCopy, nil); tObject = (AppObject) tObject->fNextObject; } ... And here's the way I tried doing it, using only a single CopyBits call. gWorldRect is the enclosing rectangle for the gworld. ... SetEmptyRgn (gCopyRgn); tObject = gFirstObject; while (tObject != nil) { if (!tObject->fVisible) { tObject = (AppObject) tObject->fNextObject; continue; } RectRgn (gRectRgn, &tObject->fAnimEnclosureRect); UnionRgn (gCopyRgn, gRectRgn, gCopyRgn); tObject = (AppObject) tObject->fNextObject; } CopyBits ((BitMap *) *tPixMap[2], (BitMap *) *tPixMap[3], &gWorldRect, &gWorldRect, srcCopy, gCopyRgn); ... The second section of code being slower than the first! o Someone else had suggested that rather than do a CopyMask call, I could do a CopyBits call with a region (apparently being 60% faster). However, while the mask for CopyMask masks out the source, the region for CopyBits masks out the destination. Therefore, unless I can change the position of a region each time I copy a sprite to the screen, I'm not sure the region param in CopyBits will help. Thanks again for all those who have helped out: further suggestions are always welcomed. I've learned a whole lot more about CopyBits and CopyMask now! Thanks, Alex -- Alex Metcalf, Mac programmer in C, C++, HyperTalk, assembler Internet, AOL, BIX: alex@metcalf.demon.co.uk AppleLink: alex@metcalf.demon.co.uk@internet# CompuServe: INTERNET:alex@metcalf.demon.co.uk Delphi: alex@metcalf.demon.co.uk@inet# FirstClass: alex@metcalf.demon.co.uk,Internet Fax (UK): (0570) 45636 Fax (US / Canada): 011 44 570 45636 --------------------------- >From mprince@mail.trincoll.edu (Matthew Prince) Subject: Blank Screen? Date: Wed, 2 Mar 1994 16:52:07 GMT Organization: Trinity College I'm curious what exactly I need to do to blank the entire screen. When I try to create a window that is the entire size of the GrayRgn I am able to cover up everything but the menu bar. Is there then a hideMenuBar command or something? Also, when I PaintRect the area defined by the GrayRgn to black a strip about the width of and right below the menu bar is left white. Any help would be appreciated. Matthew Prince mprince@mail.trincoll.edu +++++++++++++++++++++++++++ >From kenlong@netcom.com (Ken Long) Date: Thu, 3 Mar 1994 03:53:58 GMT Organization: NETCOM On-line Communication Services (408 241-9760 guest) Yes. You hide your menuBar before you show your window. That way the window is not 20 pixels down with the user's desktop textuer peeking over the top. The "HideMenuBar" and "ShowMenuBar routines in NewShuttle 1.0d3 are about as common as they come. I consulted 3 or 4 other working menu bar hide/show sources before finally deciding on that one. That Shuttle source is kind of a cheapo. It uses a "full screet window" as long as you use a 512 x 384 monitor. Unless your window is based on screenBits.bounds, as apple points out, such specific sized main windows are user unfriendly. But you also have to get fancy about positioning and/or sizing your window contents if you are going to make users with monitors over 14" happy, too. But scaling your screen objects is not very viable - it usually makes them look odd. You could do a monitor check and if it's larger than 14", don't hide the MBar and center the window. Another trick, as in "Out of This World" is to have all black outside the window. you could hide MBar, fill the rgn with black, and center your window within it. That looks okay regardless of window size (wintin reason). It that particular game, a click outside the action window updates the desktop, washing away the black. A click back in the action window, blacks it out, again. Nicely done. There are probably more 14" monitors than any other. The 12"s were popular when they first came out, but I wish I didn't get one. Some people, if the program is thoroughly done, will make sets of sizes of program parts for different monitors. The program would have to be worth it, and it would be done to increase the purchaser base potential. Here's some hide/show MBar, in C: RgnHandle mBarRgn; // First we need to "get a holt of" the MBar. short *mBarHeightPtr; short oldMBarHeight; void HideMenuBar (void) { Rect mBarRect; GrayRgn = GetGrayRgn (); mBarHeightPtr = (short *) 0x0BAA; oldMBarHeight = *mBarHeightPtr; *mBarHeightPtr = 0; mBarRect = screenBits.bounds; mBarRect.bottom = mBarRect.top + oldMBarHeight; mBarRgn = NewRgn (); RectRgn (mBarRgn, &mBarRect); UnionRgn (GrayRgn, mBarRgn, GrayRgn); PaintOne (0L, mBarRgn); } void ShowMenuBar (void) { *mBarHeightPtr = oldMBarHeight; DiffRgn (GrayRgn, mBarRgn, GrayRgn); DisposeRgn (mBarRgn); } And here's how they are called: main (void) { Do_Init_Managers (); // Gee! What's this do? Set_Data_Array (); // Some initializations. Init_Variables (); // More init. HideMenuBar (); // Take a little off the top. Set_Up_Window (); // Get ready for showtime. HideCursor (); // Get rid of "the fly." Main_Event_Loop (); // ACTION! ShowCursor (); // Action's over, bring back some control. ShowMenuBar (); // Bring this back. DisposeWindow (&window);// Dump this, an the RAM in rode in on. ExitToShell (); // Get back home, Loretta! } // We're in the Finder. -Ken- --------------------------- >From rod@faceng.anu.edu.au Subject: C code for scrollable application help Date: 3 Mar 1994 22:19:21 GMT Organization: Department of Engineering, ANU, Australia I recall from somewhere that there exists some code example for providing a scrollable text window designed for providing help information (possibly with an indexing facility). Can someone direct me to the source (if it exists)? My Freeware application has full Balloon help but I'd like to complement it with information akin to readme files. Thanks in advance. Rod +++++++++++++++++++++++++++ >From kidwell@wam.umd.edu (Christopher Bruce Kidwell) Date: 4 Mar 1994 14:30:05 GMT Organization: University of Maryland, College Park In article <2l5npaINN75o@dubhe.anu.edu.au>, wrote: >I recall from somewhere that there exists some code example >for providing a scrollable text window designed for providing >help information (possibly with an indexing facility). Can someone >direct me to the source (if it exists)? on mac.archive.umich.edu: /development/source/help.cpt.hqx It uses a styled TEXT resource to display scrollable text with a popup menu to jump to different sections. That version shows the help in a modal dialog box -- I don't know if there's a moveable modal version out there anywhere. Chris Kidwell kidwell@wam.umd.edu +++++++++++++++++++++++++++ >From chuck@gte.com (Chuck Hoffman) Date: Fri, 4 Mar 1994 15:19:53 GMT Organization: GTE Laboratories In article <2l5npaINN75o@dubhe.anu.edu.au>, rod@faceng.anu.edu.au wrote: > I recall from somewhere that there exists some code example > for providing a scrollable text window designed for providing > help information (possibly with an indexing facility). Can someone > direct me to the source (if it exists)? > > My Freeware application has full Balloon help but I'd like to complement > it with information akin to readme files. > > Thanks in advance. > > Rod You might find the Help routines useful in the sample application Chassis 6.0. The text is simple, non-styled text. The text and the selection list are both scrollable. The window is not a dialog, and can remain open while other windows are in use. The text is kept in the resource fork. The Help menu item is on the Apple menu. In release 6.1 it will be moved to the Help (baloon) menu. (6.1 will also be AppleEvent aware.) Chassis 6.0 is freeware. It is available at mac.archive.umich.edu and its mirror sites, also at CompuServe and America OnLine. Chassis 6.0 is also available directly from us at ftp.gte.com, file /pub/chuck/Chassis_6.0.sea.hqx DO NOT USE THE VERSION AT SUMEX-AIM.STANFORD.EDU. Inexplicably, they never posted the new version. The one they have, 4.3 or so, is not 32-bit clean and won't compile with THINK C 6.0. (Don't ask me... I sent the new version to them twice.) -- Chuck Hoffman GTE Laboratories, Waltham, MA, USA 617-466-2131 - ------------------------------------------------ I'm not sure why we're here, but I am sure that while we're here we're supposed to help each other. - ------------------------------------------------ +++++++++++++++++++++++++++ >From Robert Hess Date: Wed, 9 Mar 1994 02:40:56 GMT Organization: MacWEEK In article <2l7gld$kgq@cville-srv.wam.umd.edu> Christopher Bruce Kidwell, kidwell@wam.umd.edu writes: >on mac.archive.umich.edu: /development/source/help.cpt.hqx >It uses a styled TEXT resource to display scrollable text with a popup >menu to jump to different sections. That version shows the help in a >modal dialog box -- I don't know if there's a moveable modal version >out there anywhere. You!re thinking of James Walker!s !show_help!, version 2.0 of which offers a movable modal. ======================================================================= ==== Robert Hess, WEEKgeek AppleLink: WNDZSX MacWEEK CompuServe: 72511,333 301 Howard America Online: MacWEEK San Francisco, Calif. 94105 MCI: RHESS (415) 243-3576 days Internet: (415) 243-3651 fax robert_hess@macweek.ziff.com (415) 647-5549 nights I speak for myself. And sometimes not even that. ======================================================================= ==== --------------------------- >From mfi@i-link.com (MicroFrontier Inc.) Subject: Can C be as fast as Assembler? (next...on the McLaughlin Group) Date: 28 Feb 1994 09:37:13 -0600 Organization: I-Link, Ltd., Des Moines, IA, USA - 515/255-2754 OK, I've heard both sides of the story here...some developers say that C can be as fast as assembler (or at least very, very close), provided it is written well enough. Other say that C code doesn't get anywhere near the speed of assembler, no matter how it's written. Now, I would imagine that C can get closer to assembly depending on the task that is being done....what tasks would those be? What's the best way to optimize C? And....which compiler (MPW C, Symantec C, or Metrowerks C) do you think produces the fastest C code (with all optimization turned on)? Which do you think produces the best quality code (if being the fastest doesn't make it the best quality by default)? Please post responses to the net...I'm sure this is something we can all benefit from. Also, please try to keep it civil. :-) -kevin +++++++++++++++++++++++++++ >From chyang@quip.eecs.umich.edu (Chung-Hsiung Yang) Date: 28 Feb 1994 16:11:50 GMT Organization: University of Michigan EECS Dept., Ann Arbor, MI In article <2kt339$589@ilink1.i-link.com>, mfi@i-link.com (MicroFrontier Inc.) writes: |> |> |> OK, I've heard both sides of the story here...some developers say that C |> can be as fast as assembler (or at least very, very close), provided it is |> written well enough. Other say that C code doesn't get anywhere near the |> speed of assembler, no matter how it's written. |> |> Now, I would imagine that C can get closer to assembly depending on the |> task that is being done....what tasks would those be? |> |> What's the best way to optimize C? I don't think this is really a good way to look at both sides of the world. I tend to agree that assembler will be faster than C generated code because programming in assembler requires the programmer to optimize (some what) the code as you go alone because you are dealing with much lower semantics than C. On the other hand, the level of optimization one could do with C is really more dependent on the compiler itself. But look what you are doing here. What do you want to do with assembler vs. C? If you restrict yourself to the assembler world, then you are limited to pretty small programs with pretty limited software architecture. Maybe you could write routines for a small, but very fast computation that does for example some process in digital signal processing. Because of the overhead in C, you would probably not be able to achieve the speed that you could obtain with C. But imagine yourself writing a 100,000 line code in C. Quite a big project. Imagin writing the same code in assembly, you will probably have to write close to a million line or more. When you get to a million lines of code in assember, how do you optimize it? It is a scary thought, I wouldn't do it. In this case I would rather depend on a well designed C compiler to do the job. In this case, I think for very big programs C would very likely produce faster codes because there is no way for human beings to program codes that big in assembly. Also when you get to that programs that size, there are many tricks that one could play to optimize the code than assembly because, the notion of a high level software architecture such as object oriented design just could not be easily achieved by assembly. (You could do it, but it will be very hard). - Chung Yang |> And....which compiler (MPW C, Symantec C, or Metrowerks C) do you think |> produces the fastest C code (with all optimization turned on)? Which do |> you think produces the best quality code (if being the fastest doesn't |> make it the best quality by default)? |> |> Please post responses to the net...I'm sure this is something we can all |> benefit from. Also, please try to keep it civil. :-) |> |> |> |> -kevin +++++++++++++++++++++++++++ >From mssmith@afterlife.ncsc.mil (M. Scott Smith) Date: Mon, 28 Feb 1994 16:30:42 GMT Organization: The Great Beyond In article <2kt546$23o@zip.eecs.umich.edu> chyang@quip.eecs.umich.edu (Chung-Hsiung Yang) writes: >In article <2kt339$589@ilink1.i-link.com>, mfi@i-link.com (MicroFrontier Inc.) writes: >|> >|> >|> OK, I've heard both sides of the story here...some developers say that C >|> can be as fast as assembler (or at least very, very close), provided it is >|> written well enough. Other say that C code doesn't get anywhere near the >|> speed of assembler, no matter how it's written. >|> >|> Now, I would imagine that C can get closer to assembly depending on the >|> task that is being done....what tasks would those be? >|> >|> What's the best way to optimize C? Well, first, I'd say in many cases a lot of blame is put on the compiler producing "unoptimized" code when the user could in fact be optimizing their program. Meaning, often great speed increases can be seen by changing the way your program does certain things. If you do a sort, are you using a bubble sort or a quicker sort? Things like that. Once you've done a good job in that arena, then it comes time when you can benefit from better code production. Most compilers (such as Think C) have a "dissassemble" option that allow you to look at the assembly the compiler is producing. This is helpful if you know assembly; if you don't, it may not be too useful. But if you can read assembly, you can see exactly how the compiler is interpreting your code and try making modifications to your code so that the resultant assembly is better. Compilers are smart, but they're not geniouses -- often switching two lines around will signal the compiler to use some trick to make something much quicker. I wouldn't recommend writing in Assembly unless you absolutely need to; that will be weighted yourself down with concrete bricks when you want to take your program into the future. The PowerPC is an excellent case in point. The programmers who are porting their applications in two days are the ones who don't have any of their code in assembly. But a knowledge of 680x0 or PPC assembly is useful; again, you can tweak your C code around so it results in better assembly production with your compiler, without jeopardizing future compatibility. >|> And....which compiler (MPW C, Symantec C, or Metrowerks C) do you think >|> produces the fastest C code (with all optimization turned on)? Which do >|> you think produces the best quality code (if being the fastest doesn't >|> make it the best quality by default)? I think this is impossible to say. Each compiler is different, and each one might produce better code in some places and not others. Unless one has obvious code generator flaws, they're all probably pretty good. Code optimization (on the compiler's part) is tricky stuff, from what I understand. Remember: the compiler basically just does the "brute force" work of taking your C and transforming it into working, equivalent assembly. This doesn't require much "smarts" on the compiler's part. To look at the C code, and to find tricks for performing the same function with less instructions, takes great problem-solving skills and insight which humans often have, but which is difficult to duplicate in computers. Each compiler author will no doubt provide that "intelligence" in their optimizers in different ways. Each compiler probably knows different tricks. One routine of yours might result in lots of tricks with compiler X, but none in compiler Y. But with your next routine the reverse might be true. I don't know how to define "best quality" in terms other than speed. Presumably, a compiler is going to produce _100% working code_. There's no room for errors (on the compiler's part, anyway). So you'd expect any code a compiler produces to work. The next criterion is "how quickly does it work?" This is where the optimization comes in. I can't really think of better ways to measure quality of code generation, if you make the assumption that any code coming from a compiler isn't going to have any bugs introduced by the compiler. (That may not always be a valid assumption.) Just my thoughts.. Scott - - M. Scott Smith (mssmith@afterlife.ncsc.mil) Macintosh developer.. Student.. Ski bum. Eater of Kellog's Frosted Flakes. "Last stop for fuel on the information highway" +++++++++++++++++++++++++++ >From neeri@iis.ee.ethz.ch (Matthias Neeracher) Date: 28 Feb 94 18:05:12 Organization: Integrated Systems Laboratory, ETH, Zurich In article <2kt339$589@ilink1.i-link.com>, mfi@i-link.com (MicroFrontier Inc.) writes: > OK, I've heard both sides of the story here... Really? I haven't seen a hardcore assembler advocate here in a long time. > some developers say that C > can be as fast as assembler (or at least very, very close), provided it is > written well enough. Other say that C code doesn't get anywhere near the > speed of assembler, no matter how it's written. Assembler is much slower than C in several respects: - Almost all code (with a few exceptions) takes longer to write, debug, and maintain in Assembler. Note that for the same reasons, C++ is also faster than C, Eiffel is faster than C++, and Perl for some tasks is much faster than all of them. - You will find it easier to identify and rewrite speed critical parts in a C program than in an assembler program. - A C application compiled with an "Optimizing for PowerPC" compiler will run circles around your 680X0 assembler code. > Now, I would imagine that C can get closer to assembly depending on the > task that is being done....what tasks would those be? Depends also a lot on the compiler and the target processor. The 680X0 is a reasonable code generation target, and so is the PowerPC. In some ways, the PowerPC will be easier, but new factors like instruction scheduling come into play. I think assembly language progarmmers will have a harder time beating compilers on PowerPCs, since instruction scheduling is rather hard to do in one's head (Except if you are the infamous Mel, who programmed rotating disk memory machines). > What's the best way to optimize C? Use a good compiler. Profile. Rewrite critical sections. repeat. > And....which compiler (MPW C, Symantec C, or Metrowerks C) do you think > produces the fastest C code (with all optimization turned on)? ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ One problem I ahve with Mac C compilers is that at least for some of them, turning on optimizaion is too dangerous to do for an entire program. > Which do > you think produces the best quality code (if being the fastest doesn't > make it the best quality by default)? I'd take a reliable compiler over a fast compiler or one producing fast code anytime. > Also, please try to keep it civil. :-) With a topic like this?? Matthias - --- Matthias Neeracher neeri@iis.ethz.ch "And I won this ribbon in a Degradation Contest at the Teheran meeting of Junkies Anonymous" -- William Burroughs, _The Naked Lunch_ +++++++++++++++++++++++++++ >From peter@ncrpda.curtin.edu.au (Peter N Lewis) Date: 1 Mar 1994 12:03:20 +0800 Organization: NCRPDA, Curtin University mfi@i-link.com (MicroFrontier Inc.) writes: >OK, I've heard both sides of the story here...some developers say that C >can be as fast as assembler (or at least very, very close), provided it is >written well enough. Other say that C code doesn't get anywhere near the >speed of assembler, no matter how it's written. C or Pascal produce about teh same quality code. It's generally about half the speed of reasonably tight assembly code (although an important thing to remember before converting your code from C/Pascal to asm is that while you might get a double speed imporvement, redesigning the *algorithm* used may get you orders of magnitude of imporvement, and also asm can't be recompiled on the PPC to get you ~4 times speed improvement going native instead of interpreted. >Now, I would imagine that C can get closer to assembly depending on the >task that is being done....what tasks would those be? Small, simple, processor intensive things can be done more more quickly in asm (eg BlockMove, Character translation (ISO<->Mac, <->, BinHex/UU translation, etc)). Large things are better written in a high level language for the reasons stated above (easier to improve the algorithm, easier to compile on faster machines) (not to mention all the other obvious advantages (portability (kinda ;-), maintenance (kinda ;-), etc). >What's the best way to optimize C? Don't use any pointers. Pointers screw up optimizing compilers. >And....which compiler (MPW C, Symantec C, or Metrowerks C) do you think >produces the fastest C code (with all optimization turned on)? Which do >you think produces the best quality code (if being the fastest doesn't >make it the best quality by default)? No idea, they are probably all withing 10% (as is Pascal, normally on the faster side). Peter. -- Peter N Lewis Ph: +61 9 368 2055 +++++++++++++++++++++++++++ >From resnick@cogsci.uiuc.edu (Pete Resnick) Date: Mon, 28 Feb 1994 22:25:15 -0600 Organization: University of Illinois at Urbana-Champaign In article <2kueq8$865@ncrpda.curtin.edu.au>, peter@ncrpda.curtin.edu.au (Peter N Lewis) wrote: >>What's the best way to optimize C? > >Don't use any pointers. Pointers screw up optimizing compilers. What?!?! Sometimes using pointers is the only way to get a really stupid compiler to do register allocation and register loading properly. pr -- Pete Resnick (...so what is a mojo, and why would one be rising?) Graduate assistant - Philosophy Department, Gregory Hall, UIUC System manager - Cognitive Science Group, Beckman Institute, UIUC Internet: resnick@cogsci.uiuc.edu +++++++++++++++++++++++++++ >From ari@world.std.com (Ari I Halberstadt) Date: Tue, 1 Mar 1994 07:17:57 GMT Organization: The World Public Access UNIX, Brookline, MA In article , Matthias Neeracher wrote: > - Almost all code (with a few exceptions) takes longer to write, debug, and > maintain in Assembler. Note that for the same reasons, C++ is also faster > than C, Eiffel is faster than C++, and Perl for some tasks is much faster > than all of them. If only Eiffel were more widely available (like, for the mac), and a bit cheaper for us poorer programmers. Five years ago I fell in love with Eiffel, but it's still not on the mac (except for A/UX), which makes it a bit slower than C or C++. -- Ari Halberstadt ari@world.std.com #include "These beetles were long considered to be very rare because very few entomologists look for beetles in the mountains, in winter, at night, during snow storms." -- Purves W. K., et al, "Life: The Science of +++++++++++++++++++++++++++ >From jim@brunner.wf.com (Jim Brunner) Date: 28 Feb 94 14:57:34 GMT Organization: (none) In article <2kt339$589@ilink1.i-link.com>, you write: > > OK, I've heard both sides of the story here...some developers say that C > can be as fast as assembler (or at least very, very close), provided it is > written well enough. Other say that C code doesn't get anywhere near the > speed of assembler, no matter how it's written. > > Now, I would imagine that C can get closer to assembly depending on the > task that is being done....what tasks would those be? > > What's the best way to optimize C? The best way to optimize ANY program in ANY language is to take a hard look at the algorithms in use. For almost any program with noticable performance problems, 90% better speed is all in the algorithm. It's only when you get down to those last few tweeks for fractions of a percent that assembler *might* make any difference. (Of course, I'm talking in the general case - like the original poster. There are, of course, exceptions.) Try profiling your code. Run your program with a profiler (like the one included with Think C) and find out where it's spending it's time. Most likely, 90% of the time will be in 10% of the code. Look at that 10% and ignore the rest. Look at the algorithms first - searching a linked list instead of a binary tree? Make a decision: How many people does this affect, how critical is it? If the program in question isn't very critical, it might be more cost effective to ignore the problem. If not too many people use the program, it may be more cost effective to buy a faster machine. Assembly language is expensive. It's expensive in programmer time and maintenance cost. Go further only for those few lines of highly critical code - realize that these changes are not necessarily beneficial across platforms. Start by disassembling the code generated by the C compiler. Take a look at how slight coding changes affect the generated code. Only on highly critical sections of code (counting clock cycles here), go to assembler and hand code the critical section (if the compiler didn't do it well enough to begin with. These days, assembler code is almost extinct. I've seen it used recently on a small subroutine that was part of the firmware running on a DSP chip - there was a timing limitation in # of clock cycles. - - Jim Brunner (jim@brunner.wf.com) +++++++++++++++++++++++++++ >From gregor@nrlfs1.nrl.navy.mil (joe gregor) Date: Tue, 1 Mar 1994 14:29:37 GMT Organization: NRL In Article <2kueq8$865@ncrpda.curtin.edu.au>, peter@ncrpda.curtin.edu.au (Peter N Lewis) wrote: >C or Pascal produce about teh same quality code. It's generally about >half the speed of reasonably tight assembly code... >>And....which compiler (MPW C, Symantec C, or Metrowerks C) do you think >>produces the fastest C code (with all optimization turned on)? Which do >>you think produces the best quality code (if being the fastest doesn't >>make it the best quality by default)? > >No idea, they are probably all withing 10% (as is Pascal, normally on >the faster side). I had always heard/read that C was the fastest language next to asm. I *never* heard/read that Pascal was even close, let alone faster. Please identify your references so I may (re)educate myself. -- Joe ________________________________________________________________________________ Joseph Gregor | gregor@ccf.nrl.navy.mil | THIS SPACE INTENTIONALLY LEFT BLANK. tmh@eng.umd.edu | ________________________________|_______________________________________________ +++++++++++++++++++++++++++ >From jwbaxter@olympus.net (John W. Baxter) Date: Tue, 01 Mar 1994 08:35:48 -0800 Organization: Internet for the Olympic Peninsula In article <9402281957344983@brunner.wf.com>, jim@brunner.wf.com (Jim Brunner) wrote: > Go further only for those few lines of highly critical code - realize that > these changes are not necessarily beneficial across platforms. Keeping in mind that "across platforms" above in some cases includes differences among the 68000, 68020, 68030, and 68040. You may have to decide which of those you want to target (probably 68040 these days, say I who still runs a 68030), at the cost of hurting the others. -- John Baxter Port Ludlow, WA, USA [West shore, Puget Sound] jwbaxter@pt.olympus.net +++++++++++++++++++++++++++ >From mmorgan@gpu.srv.ualberta.ca (Martin Morgan) Date: 1 Mar 1994 17:31:22 GMT Organization: University of Alberta Peter N Lewis (peter@ncrpda.curtin.edu.au) wrote: : mfi@i-link.com (MicroFrontier Inc.) writes: : >What's the best way to optimize C? : Don't use any pointers. Pointers screw up optimizing compilers. Is this true? Is it true in a more restricted sense, don't use pointers in speed-critical sections of code? Martin Morgan University of Alberta +++++++++++++++++++++++++++ >From nagle@netcom.com (John Nagle) Date: Tue, 1 Mar 1994 18:40:47 GMT Organization: NETCOM On-line Communication Services (408 241-9760 guest) mfi@i-link.com (MicroFrontier Inc.) writes: >OK, I've heard both sides of the story here...some developers say that C >can be as fast as assembler (or at least very, very close), provided it is >written well enough. Other say that C code doesn't get anywhere near the >speed of assembler, no matter how it's written. Depends on the compiler. Both MPW C and Symantec C++ are worse than, say, mainframe FORTRAN compilers of the late 1960s. Good compilers for the 680x0 machines exist, but not on the Mac. MetaWare High-C is available for the 68000, but they market it to embedded systems makers, not Macs. The Sun compiler for the older 68000 Suns were reasonably good as well, and one large CAD package for the Mac used to be cross-compiled on a Sun to take advantage of this. I like to try compiling int i; char tab1[100]; tab2[100]; for (i=0; i<100; i++) tab1[i] = tab2[i]; and see what the inner loop looks like. Ideally, the inner loop should have two instructions, but I've seen as many as 12. Incidentally, using subscripts vs pointer incrementation does not make much difference with most modern compilers. Even SC++ gets this one right. The big SC++ problem is really dumb register usage. One sees lots of unnecessary register-to-register moves in SC++ output. The compiler never seems to take full advantage of all the registers available (it's a port of a compiler for Intel CPUs, which have fewer registers). In the compiler-design world, using all the registers effectively is generally considered a win even when not "optimizing", because it takes less time to figure out which register to use than to generate the register-to-register moves and stack manipulation required when doing it wrong. The global optimizer does a good job, though, except when it makes mistakes. MPW C has a better code generator but a weaker global optimizer. I tried this simple test case on a pre-release MetroWerks compiler, and it generated OK, but not spectacular code. Still, if there was a compiler for the Mac that generated state of the art optimized code, programs would be perhaps twice as fast in some cases, and somewhat smaller. John Nagle +++++++++++++++++++++++++++ >From d88-jwa@mumrik.nada.kth.se (Jon Wätte) Date: 1 Mar 1994 23:13:52 GMT Organization: Royal Institute of Technology, Stockholm, Sweden >>>What's the best way to optimize C? >>Don't use any pointers. Pointers screw up optimizing compilers. >What?!?! Sometimes using pointers is the only way to get a really stupid >compiler to do register allocation and register loading properly. Yes, but at the same time, pointers (and especially when assigned to addresses of local variables) can limit more sophisticated compilers, since they can't do a full analysis of where your pointer might point and what short-cuts it can take. -- -- Jon W{tte, h+@nada.kth.se, Mac Hacker Deluxe -- Cookie Jar: Vanilla Yoghurt with Crushed Oreos. +++++++++++++++++++++++++++ >From resnick@cogsci.uiuc.edu (Pete Resnick) Date: Tue, 01 Mar 1994 17:32:34 -0600 Organization: University of Illinois at Urbana-Champaign In article <2l0i7g$o51@news.kth.se>, d88-jwa@mumrik.nada.kth.se (Jon Wtte) wrote: >>What?!?! Sometimes using pointers is the only way to get a really stupid >>compiler to do register allocation and register loading properly. > >Yes, but at the same time, pointers (and especially when assigned to >addresses of local variables) can limit more sophisticated compilers, >since they can't do a full analysis of where your pointer might point >and what short-cuts it can take. Compilers are generally stupid. If you disassemble code resources you'll see that MPW C is stupider than THINK C, but THINK C is pretty stupid too. I am waiting for someone to release a compiler that does peep-hole optimization. Does anyone by any chance know if MetroWorks does so? Here's a rash claim (flames against my ignorance welcome): Stupid compilers are why RISC processors do better than CISC processors. If compilers were smart enough to take advantage of all of the interesting addressing modes and instructions on CISC architectures, CISCs would overall be faster at running programs than RISCs. (*Duck*) pr -- Pete Resnick (...so what is a mojo, and why would one be rising?) Graduate assistant - Philosophy Department, Gregory Hall, UIUC System manager - Cognitive Science Group, Beckman Institute, UIUC Internet: resnick@cogsci.uiuc.edu +++++++++++++++++++++++++++ >From platypus@cirrus.som.cwru.edu (Gary Kacmarcik) Date: 02 Mar 1994 01:25:16 GMT Organization: Case Western Reserve University, Cleveland, Ohio (USA) In article <2kvu5a$b06@quartz.ucs.ualberta.ca> mmorgan@gpu.srv.ualberta.ca (Martin Morgan) writes: Peter N Lewis (peter@ncrpda.curtin.edu.au) wrote: : mfi@i-link.com (MicroFrontier Inc.) writes: : >What's the best way to optimize C? : Don't use any pointers. Pointers screw up optimizing compilers. Is this true? Is it true in a more restricted sense, don't use pointers in speed-critical sections of code? using pointers does NOT directly result in slower code. there are many cases where pointers can be used to generate significantly optimized code. however, if you use pointers you should be aware of the fact that the code optimizer now can make fewer assumptions about your code, and thus it may not be able to apply certain optimizations. get a good book on compiler writing (eg: Aho, Sethi & Ullman) and read the sections on optimizing. understanding how optimizers work will greatly aid your programming: you'll have a better understanding of what the compiler can annd cannot do. -gary j kacmarcik platypus@curie.ces.cwru.edu +++++++++++++++++++++++++++ >From siegel@netcom.com (Rich Siegel) Date: Wed, 2 Mar 1994 05:41:38 GMT Organization: Bare Bones Software In article resnick@cogsci.uiuc.edu (Pete Resnick) writes: > >Compilers are generally stupid. If you disassemble code resources you'll >see that MPW C is stupider than THINK C, but THINK C is pretty stupid too. >I am waiting for someone to release a compiler that does peep-hole >optimization. Does anyone by any chance know if MetroWorks does so? Metrowerks does. So does THINK C. So does MPW C. >Here's a rash claim (flames against my ignorance welcome): Stupid >compilers are why RISC processors do better than CISC processors. If >compilers were smart enough to take advantage of all of the interesting >addressing modes and instructions on CISC architectures, CISCs would >overall be faster at running programs than RISCs. (*Duck*) I have a reality adjustment for you. On the 68020, many of the fancy addressing modes are either a wash or are actually slower than an equivalent sequence of instructions using 68000-only addressing modes. R. -- Rich Siegel % siegel@netcom.com % Principal, Bare Bones Software --> For information about BBEdit, finger bbedit@world.std.com <-- "He then proceeded to give a history of the universe, in real time." +++++++++++++++++++++++++++ >From peter@ncrpda.curtin.edu.au (Peter N Lewis) Date: 2 Mar 1994 13:20:52 +0800 Organization: NCRPDA, Curtin University >From: chewy@shell.portal.com (Paul Snively) >... >q = *p++; >... >q = *p++; >... > >Note that the above code features common subexpressions (in fact, for No, they are not cse's. To be eleigable for cse elemination, the expression must not have any side effects. I'd quote chapter and verse out of the Dragon book, but I don't have it handy. >The moral of the story is twofold: a) try to write clean, readable code >that doesn't rely on nasty compound functions, especially with >side-effects; and b) know thy optimizer. If you need help, disassemble >the code and see what your optimizer is doing behind your back. No, a) is certainly true, but b) should not be. The optimizer should never change the way your program behaves - if it does, either the optimizer is broken (like the THINK C optimizer), or your program is broken. >From: gregor@nrlfs1.nrl.navy.mil (joe gregor) >>No idea, they are probably all withing 10% (as is Pascal, normally on >>the faster side). > I had always heard/read that C was the fastest language next to asm. >I *never* heard/read that Pascal was even close, let alone faster. Please >identify your references so I may (re)educate myself. You've probably heard thousands of people tell you PCs are better than Macs. Try it and see for yourself. Pascal compilers will generally produce faster code than C compilers with equivalent source. Obviously, compilers vary a great deal, but the above is generally true. I wouldn't worry though, I expect the next generation of compilers will make C faster than Pascal, since Pascal compilers will get a lot less work done on them. Of course, then everyone will be using C++ and efficiency will be thrown right out the window, but such is life ;-) >From: mmorgan@gpu.srv.ualberta.ca (Martin Morgan) >: Don't use any pointers. Pointers screw up optimizing compilers. > >Is this true? Is it true in a more restricted sense, don't use pointers in >speed-critical sections of code? What I said is true, in that pointers screw up most really clever high level optimizations because the compiler has an impossible task of figuring out what you're doing. For example, if you do this: x = 5; for i:=1 to 100 do arr[i] = 0; end-for; y = x; (equivalent in C or Pascal). It is easy for the compiler to know that x has remained unchanged, that i is now undefined (and thus the register can be reused), that the array has been modified, that i is always between 1 and 100 and so no range checking needs to be done, that y can be assigned 5 directly, etc. If you instead do this: x=5; i=100; p = @arr[1]; while (i>0) do *p++ = 0; i--; end-while y = x; Now it is nearly impossible for the compiler to determine any of that. It has to be really clever to figure out that p only ever points to the array arr (a compiler would probably be allowed to assume this though, since it is undefined what happens if you increment a ptr outside of the area it started in). If the compiler can't figure that out, then all variables must be in memory (not registers) and all are potentially modified, so none of the optimizations above are available. Of course I wouldn't worry about this either, since most compilers don't do very much in the way of clever optimizing (and when they try, they usually screw it up)... Peter. -- Peter N Lewis Ph: +61 9 368 2055 +++++++++++++++++++++++++++ >From resnick@cogsci.uiuc.edu (Pete Resnick) Date: Wed, 02 Mar 1994 00:51:17 -0600 Organization: University of Illinois at Urbana-Champaign In article , siegel@netcom.com (Rich Siegel) wrote: >In article resnick@cogsci.uiuc.edu (Pete Resnick) writes: >> >>Compilers are generally stupid. If you disassemble code resources you'll >>see that MPW C is stupider than THINK C, but THINK C is pretty stupid too. >>I am waiting for someone to release a compiler that does peep-hole >>optimization. Does anyone by any chance know if MetroWorks does so? > >Metrowerks does. So does THINK C. So does MPW C. Surely you're kidding. I've seen MPW C move things back and forth between the same two registers (or worse, to and from the stack) oodles of times in a series of instructions with no other side effects. THINK C constantly does 'MOVE.L (A7)+,D3' followed by a 'TST.L D3' followed by a branch on condition code. And I've never seen either of them generate a DBcc instruction, even when I force feed it; I have lots of code for which THINK C generates: SUBQ.W #$1,D3 CMPI.W #$FFFF,D3 BNE.S *-$000C What *are* they looking for if not these kinds of things? As for the RISC/CISC argument I started, I've gotten lots of really cool mail in response, some in support and some against, but almost all of it saying, "It's a lot more complicated than you think." I figured as much, but I do thank everyone for their comments; I have learned a lot in the process. pr -- Pete Resnick (...so what is a mojo, and why would one be rising?) Graduate assistant - Philosophy Department, Gregory Hall, UIUC System manager - Cognitive Science Group, Beckman Institute, UIUC Internet: resnick@cogsci.uiuc.edu +++++++++++++++++++++++++++ >From d88-jwa@mumrik.nada.kth.se (Jon Wätte) Date: 2 Mar 1994 10:32:23 GMT Organization: Royal Institute of Technology, Stockholm, Sweden >I don't have my ANSI reference in front of me, but I distinctly recall >my shock upon reading something in it that made it quite clear that the >semantics of your program could differ between unoptimized and >optimized versions of your code. So far so good. >To give just one obvious example of how this could happen, consider a >function that uses a pointer p, and contains code like this: >q = *p++; >q = *p++; >let's say I compile this code without Common Subexpression Elimination. > The pointer gets incremented twice, which is probably what the author >had in mind. But if I compile with Common Subexpression Elimination >on, the compiler is completely free to evaluate the p++ once and stick >the result in a register. Oops. No, that's NOT legal, since this has a very well-defined semantic meaning. What the compiler CAN do, is change its behaviour for UNDEFINED cases, such as: foo ( q ++ , q ++ ) ; Where foo might be called as foo ( 0 , 1 ) or foo ( 1 , 0 ) depending on moon phase. Anyway, since your program shouldn't be relying on such UNDEFINED behaviour, the above allowance really isn't a problem. And since we all validate our code and use ASSERTs everywhere and step through it at the instruction level to verify it works right after we wrote it (using all available documentation) this group shouldn't have any "help me with my bug" questions either :-) :-) -- -- Jon W{tte, h+@nada.kth.se, Mac Hacker Deluxe -- "It was, in fact, cool as all get-out. Fortunately it was a little too late (historically speaking) to be groovy." -- Dennis Pelton +++++++++++++++++++++++++++ >From infosafe@panix.com (Infosafe Systems) Date: 2 Mar 1994 11:28:02 -0500 Organization: PANIX Public Access Internet and Unix, NYC In article , Rich Siegel wrote: >In article resnick@cogsci.uiuc.edu (Pete Resnick) writes: >>Here's a rash claim (flames against my ignorance welcome): Stupid ^^^^^^ >>compilers are why RISC processors do better than CISC processors. If ^^^ ^^^ ^^^^ ^^ ^^^^^^ ^^^^ ^^^^ >>compilers were smart enough to take advantage of all of the interesting >>addressing modes and instructions on CISC architectures, CISCs would >>overall be faster at running programs than RISCs. (*Duck*) I'm no expert but perhaps someone here could help me out. A few months ago I read a longish article in Byte? (I will post the reference tomorrow when I am in work, if anyone is interested) about the greatness of the MPC chip. One of the topics it discussed in detail was the fact that RISC chips have become popular, and more powerful than CISC chips for a bunch of reasons. These included fixed instruction length to eliminate bubbles in the pipeline, faster instruction decode because you don't have to spend time figuring out how long your instruction is, etc. The last point that they made was that RISC has "come out on top" *because* of improvements in compiler technology. The article said that optimizers were able to make better use of RISC instructions than CISC instructions, and this has been one of the motivating forces in developing RISC chips for workstations, where you have *good* compilers ;-) Opinions? Let the flames begin! (Again, I will post the article and a better summary, if anyone is interested) Bradford Smith +++++++++++++++++++++++++++ >From siegel@netcom.com (Rich Siegel) Date: Wed, 2 Mar 1994 16:06:46 GMT Organization: Bare Bones Software In article resnick@cogsci.uiuc.edu (Pete Resnick) writes: >In article , siegel@netcom.com (Rich Siegel) wrote: > >>In article resnick@cogsci.uiuc.edu (Pete Resnick) writes: >>> >>>Compilers are generally stupid. If you disassemble code resources you'll >>>see that MPW C is stupider than THINK C, but THINK C is pretty stupid too. >>>I am waiting for someone to release a compiler that does peep-hole >>>optimization. Does anyone by any chance know if MetroWorks does so? >> >>Metrowerks does. So does THINK C. So does MPW C. > >Surely you're kidding. I've seen MPW C move things back and forth between >the same two registers (or worse, to and from the stack) oodles of times >in a series of instructions with no other side effects. THINK C constantly >does 'MOVE.L (A7)+,D3' followed by a 'TST.L D3' followed by a branch on >condition code. And I've never seen either of them generate a DBcc >instruction, even when I force feed it; I have lots of code for which >THINK C generates: > > SUBQ.W #$1,D3 > CMPI.W #$FFFF,D3 > BNE.S *-$000C > >What *are* they looking for if not these kinds of things? I'm not kidding, and don't call me Shirley. :-) Don't confuse instruction selection and target analysis with peepholing, and DBRA is not a cure-all. One thing that THINK C (and THINK Pascal) do pretty well is branch-and-loop optimization (a "peephole" operation). All of the above-mentioned compilers do -some- peepholing. It may not be as thorough as you might like it, but it's done. R. -- Rich Siegel % siegel@netcom.com % Principal, Bare Bones Software --> For information about BBEdit, finger bbedit@world.std.com <-- "...yeah, I inhaled, and then I drank the bong water. So what're you gonna do about it?" - Dennis Miller, on Bill Clinton +++++++++++++++++++++++++++ >From ari@world.std.com (Ari I Halberstadt) Date: Wed, 2 Mar 1994 17:00:16 GMT Organization: The World Public Access UNIX, Brookline, MA In article , Pete Resnick wrote: >condition code. And I've never seen either of them generate a DBcc >instruction, even when I force feed it; I have lots of code for which >THINK C generates: > > SUBQ.W #$1,D3 > CMPI.W #$FFFF,D3 > BNE.S *-$000C > >What *are* they looking for if not these kinds of things? Try structure assignment in THINK C. The structure has to be big enough, or the compiler will just use word or long word move instructions. Here's an example of a DBF instruction: static void x(void) { struct { long a, b, c, d, e, f, g; } a, b; a = b; } x: 00000000 LINK A6,#$FFC8 00000004 LEA $FFE4(A6),A0 00000008 LEA $FFC8(A6),A1 0000000C MOVEQ #$06,D0 0000000E MOVE.L (A1)+,(A0)+ 00000010 DBF D0,*-$0002 ; 0000000E 00000014 UNLK A6 00000016 RTS 0000001C -- Ari Halberstadt ari@world.std.com #include "These beetles were long considered to be very rare because very few entomologists look for beetles in the mountains, in winter, at night, during snow storms." -- Purves W. K., et al, "Life: The Science of +++++++++++++++++++++++++++ >From jwbaxter@olympus.net (John W. Baxter) Date: Wed, 02 Mar 1994 10:03:00 -0800 Organization: Internet for the Olympic Peninsula In article <2l2eqi$j40@panix2.panix.com>, infosafe@panix.com (Infosafe Systems) wrote: > I'm no expert but perhaps someone here could help me out. A few months > ago I read a longish article in Byte? (I will post the reference > tomorrow when I am in work, if anyone is interested) about the greatness > of the MPC chip. > > One of the topics it discussed in detail was the fact that RISC chips have > become popular, and more powerful than CISC chips for a bunch of reasons. > These included fixed instruction length to eliminate bubbles in the > pipeline, faster instruction decode because you don't have to spend time > figuring out how long your instruction is, etc. > > The last point that they made was that RISC has "come out on top" *because* > of improvements in compiler technology. The article said that optimizers > were able to make better use of RISC instructions than CISC instructions, > and this has been one of the motivating forces in developing RISC chips > for workstations, where you have *good* compilers ;-) I've been around these crazy machines since around 1959 (more like 1952 if I get to count helping mother with her "homework" with her computer usage at JPL (she used IBM 650, ElectroData <> #1, IBM 704)). There have been periodic waves of RISCness, followed by retreats to CISCness. But the R is gradually winning...each retreat to the C direction goes a little less far. I'm beginning to thing that the current RISC wave is the real thing, and that there won't be much retreat. And I tend to agree that the advances in compiler technology are a major reason why RISC may well happen this time. In any case, as viewed from the late 1950s, everything we run today is RISC. Consider the NCR 304: 3-address instructions (add A to B putting the result in C). One of the interesting single machine instructions was "write-copy-read": write this record to that tape, read records from that other tape and copy them to that tape until one has a key which matches this test, and give me the matching record. Absolutely perfect for father-son file updates, which aren't done much any more. The 304 also had single instruction in-memory sorts and merges. -- John Baxter Port Ludlow, WA, USA [West shore, Puget Sound] jwbaxter@pt.olympus.net +++++++++++++++++++++++++++ >From mxmora@unix.sri.com (Matt Mora) Date: 2 Mar 1994 11:10:40 -0800 Organization: SRI International, Menlo Park, CA In article resnick@cogsci.uiuc.edu (Pete Resnick) writes: >Here's a rash claim (flames against my ignorance welcome): Stupid >compilers are why RISC processors do better than CISC processors. If >compilers were smart enough to take advantage of all of the interesting >addressing modes and instructions on CISC architectures, CISCs would >overall be faster at running programs than RISCs. (*Duck*) I don't think could be possible. Even though its called RISC the PowerPC chip has more instructions than the 68020 or so I've read. Its the complexity of the instruction that matters. An instuction on a RISC takes at max 5 clocks, but on a CISC who knows how long a certain intruction will take. There goes your pipelining. The beauty of RISC is its simplicity. With few transistors and less logic, its easy to get faster CPU speeds. That's why even before the first PowerPc mac shipped, its already be upgraded from 66 mhz to 80 mhz. A slower running CISC will never be able to keep up. Remember the 32k of on chip cache takes up a big chuck of the die size. Without the cache the die would be even smaller. (but slower) CISC is doomed because the art of writing tight fast code is becoming obsolete. If compiler writers won't do it why should we. Image how fast things would be on RISC with hand tuned assembly. Xavier -- ___________________________________________________________ Matthew Xavier Mora Matt_Mora@qm.sri.com SRI International mxmora@unix.sri.com 333 Ravenswood Ave Menlo Park, CA. 94025 +++++++++++++++++++++++++++ >From nagle@netcom.com (John Nagle) Date: Wed, 2 Mar 1994 19:30:41 GMT Organization: NETCOM On-line Communication Services (408 241-9760 guest) siegel@netcom.com (Rich Siegel) writes: >In article resnick@cogsci.uiuc.edu (Pete Resnick) writes: >>Compilers are generally stupid. If you disassemble code resources you'll >>see that MPW C is stupider than THINK C, but THINK C is pretty stupid too. >>I am waiting for someone to release a compiler that does peep-hole >>optimization. Does anyone by any chance know if MetroWorks does so? >Metrowerks does. So does THINK C. So does MPW C. But SC++ doesn't, judging from the code. >>Here's a rash claim (flames against my ignorance welcome): Stupid >>compilers are why RISC processors do better than CISC processors. If >>compilers were smart enough to take advantage of all of the interesting >>addressing modes and instructions on CISC architectures, CISCs would >>overall be faster at running programs than RISCs. (*Duck*) >I have a reality adjustment for you. On the 68020, many of the fancy >addressing modes are either a wash or are actually slower than an >equivalent sequence of instructions using 68000-only addressing modes. That's a problem with many machines with variable-length instructions. Check the timings for the 68030 and '040, though; the ratios get better as you throw more transistors at the problem. John Nagle +++++++++++++++++++++++++++ >From jvp@tools1.ee.iastate.edu (Jim Van Peursem) Date: 2 Mar 94 21:24:34 GMT Organization: Iowa State University, Ames, Iowa In <2l2obg$fca@unix.sri.com> mxmora@unix.sri.com (Matt Mora) writes: >In article resnick@cogsci.uiuc.edu (Pete Resnick) writes: >>Here's a rash claim (flames against my ignorance welcome): Stupid >>compilers are why RISC processors do better than CISC processors. If >>compilers were smart enough to take advantage of all of the interesting >>addressing modes and instructions on CISC architectures, CISCs would >>overall be faster at running programs than RISCs. (*Duck*) >I don't think could be possible. Even though its called RISC the PowerPC >chip has more instructions than the 68020 or so I've read. Its the >complexity of the instruction that matters. An instuction on a RISC takes at >max 5 clocks, but on a CISC who knows how long a certain intruction >will take. There goes your pipelining. Ah yes, the wandering definition of RISC. I saw a nice summary of what RISC means in comp.arch awhile back. It's more a function of cycles-per-instruction and number of registers, etc than the number of instructions supported. I agree with Pete that originally, RISC was driven by the fact that most compilers simply didn't support the complex instructions in some chips. But more accurately, some complex instructions in some chips were slower than their counter-part simple instructions to perform the same task. The VAX had several of these as I recall. Anyway, your definition of RISC taking a max 5 clock cycles is wrong. That depends on the depth of the pipe and other factors. >The beauty of RISC is its simplicity. With few transistors and less >logic, its easy to get faster CPU speeds. That's why even before the >first PowerPc mac shipped, its already be upgraded from 66 mhz to 80 mhz. But these days, the RISC processors have around the same number of transistors as their CISC counterparts. It's more a function of the regularity of the instructions. Since all instructions are the same size, and decode the same, it's easy to pipeline them and keep the pipe full. I say the reason RISC is winning the game now is because of the advancements in both the pipelines and compilers. >Image how fast things would be on RISC >with hand tuned assembly. It would be slower. :) Remembering all of the pipeline hazards by hand is very complex. A compiler can do a much better job of these kinds of scheduling issues for any reasonably sized routine. +---------------------------------------------------------------+ | Jim Van Peursem - Ph.D. Candidate - Ham Radio -> KE0PH | | Department of Electrical Engineering and Computer Engineering | | Iowa State University - Ames, IA 50011 : (515) 294-8339 | | internet - jvp@iastate.edu -or- jvp@cpre1.ee.iastate.edu | +---------------------------------------------------------------+ +++++++++++++++++++++++++++ >From jim@brunner.wf.com (Jim Brunner) Date: 2 Mar 94 02:57:28 GMT Organization: (none) In article , you write: > > Here's a rash claim (flames against my ignorance welcome): Stupid > compilers are why RISC processors do better than CISC processors. If > compilers were smart enough to take advantage of all of the interesting > addressing modes and instructions on CISC architectures, CISCs would > overall be faster at running programs than RISCs. (*Duck*) Actually, good RISC compilers are MORE difficult because of the difficulty of doing pipeline optimization. - - Jim Brunner (jim@brunner.wf.com) +++++++++++++++++++++++++++ >From jtbell@cs1.presby.edu (Jon Bell) Date: Wed, 2 Mar 94 23:06:40 GMT Organization: Presbyterian College, Clinton, South Carolina USA In article , joe gregor wrote: >In Article <2kueq8$865@ncrpda.curtin.edu.au>, peter@ncrpda.curtin.edu.au >(Peter N Lewis) wrote: > >>C or Pascal produce about teh same quality code. It's generally about >>half the speed of reasonably tight assembly code... > > I had always heard/read that C was the fastest language next to asm. >I *never* heard/read that Pascal was even close, let alone faster. Please >identify your references so I may (re)educate myself. It makes no sense to talk about the "speed" of a language (or rather, its compiled code) without reference to the compiler and the computer it's running on. There is nothing intrinsic in the design of Pascal or C that would make one faster than the other. What counts is the implementation. On some computers, C is indeed much faster than Pascal because their C compilers are more "efficient" in that respect than their Pascal compilers. On the Mac, this is not the case. The two languages run just about neck and neck when you compare (say) Think Pascal with Think C or MPW Pascal with MPW C. I don't have specific references handy, but I'll browse through my back issues of MacTutor and see if I can find something to post if no one beats me to it. -- Jon Bell Presbyterian College Dept. of Physics and Computer Science Clinton, South Carolina USA +++++++++++++++++++++++++++ >From especkma@reed.edu (Erik A. Speckman) Date: 3 Mar 1994 06:56:45 GMT Organization: Hellmouth-Heater Democrat In article , Jim Van Peursem wrote: > I agree with Pete that originally, RISC was driven by the fact that >most compilers simply didn't support the complex instructions in some >chips. But more accurately, some complex instructions in some chips were >slower than their counter-part simple instructions to perform the same >task. The VAX had several of these as I recall. Anyway, your definition >of RISC taking a max 5 clock cycles is wrong. That depends on the depth >of the pipe and other factors. No, no, no its that implimenting complex instructions costs silicon that could be better used increacing pipeline complexity or chache and speeding up all operations. No, its a desert topping. No, it is all those things and a desert topping to boot. > -- ____________________________________________________________________________ Erik Speckman especkma@romulus.reed.edu GBDS Workstation- A high-performance microcomputer designed to run benchmarks. +++++++++++++++++++++++++++ >From rang@winternet.mpls.mn.us (Anton Rang) Date: 03 Mar 1994 14:37:47 GMT Organization: Minnesota Angsters In article resnick@cogsci.uiuc.edu (Pete Resnick) writes: >In article <2kueq8$865@ncrpda.curtin.edu.au>, peter@ncrpda.curtin.edu.au >(Peter N Lewis) wrote: > >>>What's the best way to optimize C? >> >>Don't use any pointers. Pointers screw up optimizing compilers. > >What?!?! Sometimes using pointers is the only way to get a really stupid >compiler to do register allocation and register loading properly. Yes, but if you have a really *smart* compiler, pointers screw it up royally, especially if you are passing parameters around by address. Once you take the address of an object, almost any access through a pointer stops the compiler from being able to optimize it. So you're often better off to use a temporary variable, like -- temp_x = x; do_something(&temp_x); x = temp_x; and keep 'x' local, so the compiler can (a) keep it in a register, and (b) assume that its value isn't changed by almost *every* call and every assignment through a pointer. Of course, using the best algorithms is still the best way to optimize *any* language. -- Anton -- Anton Rang (rang@acm.org) +++++++++++++++++++++++++++ >From Brad Koehn Date: 4 Mar 1994 01:58:54 GMT Organization: University of Wisconsin In article <2l17nk$1ku@ncrpda.curtin.edu.au> Peter N Lewis, peter@ncrpda.curtin.edu.au writes: >Try it and see for yourself. Pascal compilers will generally produce faster >code than C compilers with equivalent source. Obviously, compilers vary >a great deal, but the above is generally true. I wouldn't worry though, >I expect the next generation of compilers will make C faster than Pascal, >since Pascal compilers will get a lot less work done on them. Of course, >then everyone will be using C++ and efficiency will be thrown right out >the window, but such is life ;-) Heck, check out the XLC and XLC++ compilers from IBM. Talk about well-built! From what I understand, Apple was using them for quite a while to compile for PPC (ahh, MPW, you dog you). Anyway, these two beasties can do some really nice magic with your code. And IBM just keeps improving them. Now, if only the Mac had it so good... Oh, that's right, PowerOpen lets me use both AIX and MAS on the same machine! So I can use XLC++ with my Mac code! Life is so good! _________________________________________________________________________ Brad Koehn Data Transformations, Inc. koehn@macc.wisc.edu +++++++++++++++++++++++++++ >From Brad Koehn Date: 4 Mar 1994 02:06:09 GMT Organization: University of Wisconsin In article Anton Rang, rang@winternet.mpls.mn.us writes: > Yes, but if you have a really *smart* compiler, pointers screw it up >royally, especially if you are passing parameters around by address. >Once you take the address of an object, almost any access through a >pointer stops the compiler from being able to optimize it. So you're >often better off to use a temporary variable, like -- > > temp_x = x; > do_something(&temp_x); > x = temp_x; > >and keep 'x' local, so the compiler can (a) keep it in a register, and >(b) assume that its value isn't changed by almost *every* call and >every assignment through a pointer. Can't the compiler just check the code for do_something and see if it changes temp_x? I realize it would be a real pain for compilers, but so what? Life is pain. Anyone who tells you otherwise is trying to sell you something.* Just build a table for each function that checks to see if the parameters are changed. Sigh. I guess I should have taken that compiler class... * The Man in Black, "The Princess Bride" _________________________________________________________________________ Brad Koehn Data Transformations, Inc. koehn@macc.wisc.edu +++++++++++++++++++++++++++ >From pottier@prao.ens.fr (Francois Pottier) Date: 4 Mar 1994 14:26:33 GMT Organization: Ecole Normale Superieure, PARIS, France In article <2l652h$aa6@news.doit.wisc.edu>, Brad Koehn wrote: >> temp_x = x; >> do_something(&temp_x); >> x = temp_x; >Can't the compiler just check the code for do_something and see if it >changes temp_x? I realize it would be a real pain for compilers, but so No, it can't. This looks like a typical undecidable problem. In a language with pointers like C or Pascal, there are tons of ways of modifying a variable. For instance, look at this: long x, y; long *p; p = &x; p++; *p = 0; This code modifies y. Hard to tell, uh ? I think it should be relatively easy to demonstrate that the problem is undecidable. I could try writing a proof if you wish. -- Francois Pottier ___ ___ _ _ / ___ ___ ___ pottier@dmi.ens.fr /_ /__/ /_| /| / / / / / / /__ / / \ / | / |/ /___ /__/ / ___/ _ / +++++++++++++++++++++++++++ >From mmorgan@gpu.srv.ualberta.ca (Martin Morgan) Date: 4 Mar 1994 16:02:53 GMT Organization: University of Alberta Francois Pottier (pottier@prao.ens.fr) wrote: : Brad Koehn wrote: : >> temp_x = x; : >> do_something(&temp_x); : >> x = temp_x; : >Can't the compiler just check the code for do_something and see if it : >changes temp_x? I realize it would be a real pain for compilers, but so : No, it can't. This looks like a typical undecidable problem. In a language or the user declare do_something as do_something (const type-of-x *)?. Is that a legal declaration? : variable. For instance, look at this: : long x, y; : long *p; : p = &x; : p++; : *p = 0; : This code modifies y. Hard to tell, uh ? surely memory allocation of x and y is left to the compiler, so there's no guarantee that anything relevant to the snippet is modified by *p = 0? Martin Morgan +++++++++++++++++++++++++++ >From rang@winternet.mpls.mn.us (Anton Rang) Date: 05 Mar 1994 15:44:45 GMT Organization: Minnesota Angsters In article <2l652h$aa6@news.doit.wisc.edu> Brad Koehn writes: >> temp_x = x; >> do_something(&temp_x); >> x = temp_x; > >Can't the compiler just check the code for do_something and see if it >changes temp_x? I realize it would be a real pain for compilers, but so >what? Yes and no. The problem is that C's separate compilation model calls for "compile a bunch of functions so that they all work correctly independently; at link time, hook them together." To make this work right, you need to defer code generation until linking. There are Ada development systems which do this (they need to generate extremely tight code for embedded systems). However, because of C's ubiquitous pointers, this trick only works for very simple functions. Figuring out what variables a given procedure call might modify, or even an approximation to it, in the presence of globals or structures containing pointers, is non-trivial. -- Anton Rang (rang@acm.org) +++++++++++++++++++++++++++ >From zstern@adobe.com (Zalman Stern) Date: Mon, 7 Mar 1994 02:50:34 GMT Organization: Adobe Systems Incorporated Anton Rang writes > Yes and no. The problem is that C's separate compilation model > calls for "compile a bunch of functions so that they all work > correctly independently; at link time, hook them together." To make > this work right, you need to defer code generation until linking. > There are Ada development systems which do this (they need to generate > extremely tight code for embedded systems). MIPS' C compiler/linker and the Plan 9 C compiler/linker (from AT&T Bell Labs) both offer link time code generation and optimization. I'm sure there are others. (Part of the problem with discussing a topic like this in the Mac community is most Mac programmers have limited experience with the broad realm of tools that run on other platforms.) I'd be happy with a Mac C compiler that was up to the state-of-the-art with regard to intra-procedure optimization. (Though I insist on automatic inlining of appropriate file scope static functions.) -- Zalman Stern zalman@adobe.com (415) 962 3824 Adobe Systems, 1585 Charleston Rd., POB 7900, Mountain View, CA 94039-7900 "Do right, and risk consequences." Motto of Sam Houston (via Molly Ivins) +++++++++++++++++++++++++++ >From armb@setanta.demon.co.uk (Alan Braggins) Date: Mon, 7 Mar 1994 17:22:02 GMT Organization: Setanta Software In article <2l7m3d$jil@quartz.ucs.ualberta.ca> mmorgan@gpu.srv.ualberta.ca (Martin Morgan) writes: : >Can't the compiler just check the code for do_something and see if it : >changes temp_x? I realize it would be a real pain for compilers, but so : No, it can't. This looks like a typical undecidable problem. In a language or the user declare do_something as do_something (const type-of-x *)?. Is that a legal declaration? It is. But do_something is allowed to cast away const with implementation defined results. -- Alan Braggins armb@setanta.demon.co.uk abraggins@cix.compulink.co.uk "Any technology distinguishable from magic is insufficiently advanced" +++++++++++++++++++++++++++ >From peter@ncrpda.curtin.edu.au (Peter N Lewis) Date: 9 Mar 1994 11:41:15 +0800 Organization: NCRPDA, Curtin University scott.m.silver@dartmouth.edu (Scott M. Silver) writes: >All the books I've read about RISC say this is true. I think this is >from the standpoint that it is also easier to optimize for RISC chips >because there aren't 9 million addressing modes, and eighty different >ways to do things. Yep, it was great writing an optimizing compiler for the ARM (Acorn RISC Machine) (now used in the Newton). We'd sit down and look at the code it produced and we could come up with a thousand different ways of doing the same thing, and they all took exactly the same amount of time! Very nice. Much more pleasant than sitting down with a 68040 manual and spending several days comparing timing before deciding that it's non- deterministic ;-) Peter. -- Peter N Lewis Ph: +61 9 368 2055 +++++++++++++++++++++++++++ >From tom@wcc.oz.au (Tom Evans) Date: 10 Mar 94 09:05:12 GMT Organization: Webster Computer Corp, Melbourne, Australia In article <2kueq8$865@ncrpda.curtin.edu.au>, peter@ncrpda.curtin.edu.au (Peter N Lewis) surprisingly writes: > mfi@i-link.com (MicroFrontier Inc.) writes: > > >And....which compiler (MPW C, Symantec C, or Metrowerks C) do you think > >produces the fastest C code (with all optimization turned on)? Which do Don't run MPW C (V3.3) with "-opt full" - it can't even printf() if you do! > No idea, they are probably all withing 10% (as is Pascal, normally on > the faster side). I wish it were so Peter, but it ain't, not unless they're all within 10% of being 30% slower than they should be. I compile on a Macintosh under MPW and on a Sun 3 under its compiler or gcc. The Mac is a 33MHz 68030. The Sun is a 20MHz 68020. When I benchmark them against each other, they always run at about the SAME SPEED. The Sun compiles the following: void testcopy(char *p1, char *p2, short length) { while (length--) *p1++ = *p2++; } To: testcopy: linkw a6,#-0x10 testcopy+4: movl a6@(0xc),a0 testcopy+8: movl a6@(8),a1 testcopy+0xc: movw a6@(0x12),d0 testcopy+0x10: bras _memcpy+0x14 testcopy+0x12: movb a0@+,a1@+ testcopy+0x14: dbra d0,_memcpy+0x12 testcopy+0x18: unlk a6 testcopy+0x1a: rts This is pretty much exactly as an assembler programmer might do it (but a real assembler programmer would unroll the loop, as would a real C programmer :-). MPW with optimisation on makes the following botch of it: 00000000: LINK A6,#$0000 00000004: MOVEM.L D7/A3/A4,-(A7) 00000008: MOVE.W $0012(A6),D7 0000000C: MOVEA.L $000C(A6),A3 00000010: MOVEA.L $0008(A6),A4 00000014: BRA.S *+$0004 ; 00000018 00000016: MOVE.B (A3)+,(A4)+ 00000018: MOVE.W D7,D0 0000001A: SUBQ.W #$1,D7 0000001C: TST.W D0 0000001E: BNE.S *-$0008 ; 00000016 00000020: MOVEM.L -$000C(A6),D7/A3/A4 00000026: UNLK A6 00000028: RTS MPW has used 42 bytes of code to do what the Sun did in 28 (50% more), and it takes 40% longer to do it. There are 2 instructions in the Sun's inner loop, versus 5 with MPW. Benchmark figures - I copied the Sun's assembler code to the Mac and assembled it there to get the "Mac running Sun compiled" figure: To run 100000 loops of the above function with "len = 10" takes: Sun running Mac running Mac running Sun compiled Mac compiled Sun compiled -------------------------------------------- 23 s 22 s 15 s The Mac is 47% faster running the same binary, but only 5% faster running the same "source". MPW generated code that takes 40% longer to execute than the Sun-compiled code did. Yes, this is a slightly contrived example (a - shock, horror, BENCHMARK!) - it took a tiny amount of work (and knowledge) to get the Sun to use the DBRA, and not a subtract-and-branch, but at least it doesn't copy it before comparing. However, whenever I've looked at MPW's output, I've always seen unnecessary copying between registers, unnecessary masking, weird testing, operations that can be done in one line of code taking 4 or 5 lines. I've foung gcc does about the same job as the Sun compiler does (i.e. very good). Does this mean that if the Macintosh ROMs and System were recompiled with gcc the system would be 30% smaller and 50% faster? :-) > >What's the best way to optimize C? > > Don't use any pointers. Pointers screw up optimizing compilers. MPW doesn't count as an "optimising compiler" then, so it doesn't matter :-). Use pointers in preference to array references though. Back to the original question - has anyone compared MPW and Symantec and Metrowerks (and the latest gnu port perhaps) head-on-head? Compared code SIZE and SPEED? ======================== Tom Evans tom@wcc.oz.au Webster Computer Corp P/L, 11 Glenvale Crescent Mulgrave, Melbourne 3170 Victoria, Australia 61-3-560-1100 FAX ...560-0067 A.C.N. 004 818 455 wcc@cup.portal.com, AppleLink: "WEBSTER.USA" 2109 O'Toole Avenue, Suite J. San Jose, CA 95131-1338 USA 1-408-954-8054 FAX 1-408-954-1832 AppleLink WEBSTER.USA +++++++++++++++++++++++++++ >From peirce@outpost.SF-Bay.org (Michael Peirce) Date: Thu, 10 Mar 94 09:04:22 PST Organization: Peirce Software, Inc. In article <3731@wcc.oz.au> (comp.sys.mac.programmer), tom@wcc.oz.au (Tom Evans) writes: > Does this mean that if the Macintosh ROMs and System were recompiled with > gcc the system would be 30% smaller and 50% faster? :-) You're assuming the "system" is written in C. Parts are, but bigger parts are written in plain old assembler. Other parts are written in Pascal. Some parts are highly hand optomized to run best on the specific processor they are destine to run on since the code lives in a ROM that won't ever be plugged into another processor type. BlockMove and CopyBits come to mind. I understand major parts of the system are (have been) rewritten in C to make them portable (to PowerPC and x86). -- Michael Peirce -- peirce@outpost.sf-bay.org -- Peirce Software, Inc. -- 719 Hibiscus Place, Suite 301 -- -- San Jose, California USA 95117 -- Makers of: Smoothie & -- voice: +1.408.244.6554 fax: +1.408.244.6882 -- Peirce Print Tools -- AppleLink: peirce & America Online: AFC Peirce +++++++++++++++++++++++++++ >From s_heidri@irau32.ira.uka.de (Dietmar Heidrich) Date: 17 Mar 1994 13:39:58 GMT Organization: University of Karlsruhe, FRG In article , gregor@nrlfs1.nrl.navy.mil (joe gregor) writes: |> |> I had always heard/read that C was the fastest language next to asm. |> I *never* heard/read that Pascal was even close, let alone faster. Please |> identify your references so I may (re)educate myself. The implementation of a language can be fast or slow, not the language itself. For some reasons not well understood (unless you agree with Richard Gabriel in his JOOP article), C is widespread used and therefore gets most support efforts (at least on other platforms). -- Dietmar Heidrich, Universitaet Karlsruhe, Germany "Die Hoffnung auf den Tod ist das einzige, was mich am Leben erhaelt." --------------------------- >From mbayme@bih.harvard.edu (Michael J. Bayme, M.D.) Subject: Color Terminal Emulator Date: Sun, 06 Mar 1994 13:37:29 -0500 Organization: Beth Israel Hospital Boston Hi! I'm writing a color terminal emultor for my hospital's system - and it's slow. I use srcCopy and lots of DrawChars - it's slow. I've seen tech notes about a bug in system 7 that makes this sort of code run slowly. Is this true? Are there work-arounds available. Thanks, Michael Bayme +++++++++++++++++++++++++++ >From leonardr@netcom.com (Leonard Rosenthol) Date: Sun, 6 Mar 1994 20:32:26 GMT Organization: Aladdin Systems, Inc. In article , mbayme@bih.harvard.edu (Michael J. Bayme, M.D.) wrote: > Hi! I'm writing a color terminal emultor for my hospital's system - and > it's slow. I use srcCopy and lots of DrawChars - it's slow. I've seen tech > notes about a bug in system 7 that makes this sort of code run slowly. Is > this true? Are there work-arounds available. > The only "problem" with System 7 and color has to do with calling SetCtlValue() on things like scrollbars to often. Your problem is more likely the calls to DrawChar(). Try doing some buffering and calling DrawString() or DrawText() instead, that will speed things up. Also look for multiple calls to setting/resetting colors, text mode, etc. The things a good profiler would find. Leonard - ------------------------------------------------------------------------ Leonard Rosenthol Internet: leonardr@netcom.com Director of Advanced Technology AppleLink: MACgician Aladdin Systems, Inc. GEnie: MACgician +++++++++++++++++++++++++++ >From trygve@apple.com (Trygve Isaacson) Date: Thu, 10 Mar 1994 01:06:06 -0800 Organization: Apple Computer, Inc. In article , mbayme@bih.harvard.edu (Michael J. Bayme, M.D.) wrote: > Hi! I'm writing a color terminal emultor for my hospital's system - and > it's slow. I use srcCopy and lots of DrawChars - it's slow. I've seen tech > notes about a bug in system 7 that makes this sort of code run slowly. Is > this true? Are there work-arounds available. > Thanks, Michael Bayme Fortunately, yes. Terminal emulators were among the first to hit this problem because few other programs' performance relies on the speed of drawing text on a colored background. The solution is to use srcOr instead of srcCopy (srcOr is fast). But this means you are responsible for filling in the background color before drawing. So: - First, paint the invalid area with the background color - Then, draw the text with the foreground color using srcOr Unfortunately, this two-phase drawing is visibly a bit uglier than srcCopy, but if you spend a little extra effort to do it offscreen, it will look even better than before. While I'm yacking, here are a couple of other speed tips: 1) Don't draw character by character: instead, draw an entire run of text at a time, where a run is defined as all adjacent characters that can be drawn with the same pen/color/style/whatever. (OK, this is obvious; otherwise your drawing would already be intolerably slow.) 2) Optimize out whitespace: move the pen instead of drawing blanks. Of course, this assumes you can calculate the character width ahead of time, which assumes you're using a monospaced font. Note that boldface throws a wrench in things unless your font's bold maintains the same character width as plain, as does our Noiro font shipped with the SNA¥ps emulators. 3) Optimize out areas (rows/cols) that don't need to be drawn, such as areas outside the window update region, and areas outside the modified data. In other words, don't let clipping do all your work for you. It's faster to calculate what doesn't need to be drawn than to actually draw text that will be clipped. 4) When you get new data to draw, don't just invalidate and sit there waiting for an update event; draw immediately. Hmmm, that's it off the top of my head.... Good luck... Trygve Isaacson SNA¥ps engineer Apple Computer, Inc. +++++++++++++++++++++++++++ >From msouth@BIX.com (msouth on BIX) Date: 12 Mar 94 04:28:12 GMT Organization: Delphi Internet Services Corporation More terminal-emulation tips of varying usefullness: 5) Don't scroll with every linefeed received. Instead, save up text and scroll a certain number of times per second. 5) Get complicated. Most of the CPU time is probablly being used to scroll text up one line with every linefeed received. Instead, save up incoming text (by drawing to offscreen bitmap?), and scroll in three or four lines at a time. You can't see more than 20 frames or so a second, so 60 lines a secord (for instance) would be wasting a lot of time. Even 5 or 10 refreshes a second can be bearable. Mike South --------------------------- >From warwick_j@cubldr.colorado.edu Subject: DrawString + Ellipsis character ? Date: Thu, 10 Mar 1994 10:35:24 GMT Organization: University of Colorado, Boulder What is the best way to draw a Str255 into a Rect, abbreviating the string if it doesn't fit by putting an ellipsis at the end? The Finder does this for its By Name views, for example, when one of the fields doesn't fit into the space provided. I seem to remember seeing a routine to do this documented somewhere. Obviously it would be simple to write, but I'd hate to reinvent the wheel... Nick. +++++++++++++++++++++++++++ >From Lars.Farm@nts.mh.se (Lars Farm) Date: Thu, 10 Mar 1994 14:34:24 +0100 Organization: Mid Sweden University In article <1994Mar10.033524.1@cubldr.colorado.edu>, warwick_j@cubldr.colorado.edu wrote: > What is the best way to draw a Str255 into a Rect, abbreviating the > string if it doesn't fit by putting an ellipsis at the end? Use the Script Manager routine TruncString() or TruncText(). See: TextUtils.h or Script.h -- Lars.Farm@nts.mh.se +++++++++++++++++++++++++++ >From harveyj@dunx1.ocs.drexel.edu. (John Harvey) Date: Thu, 10 Mar 1994 16:36:04 GMT Organization: Drexel University In article <1994Mar10.033524.1@cubldr.colorado.edu> warwick_j@cubldr.colorado.edu writes: > What is the best way to draw a Str255 into a Rect, abbreviating the > string if it doesn't fit by putting an ellipsis at the end? Use either of these two traps: FUNCTION TruncText (width: Integer; textPtr: Ptr; VAR length: Integer; truncWhere: TruncCode): Integer; or FUNCTION TruncString (width: Integer; VAR theString: Str255; truncWhere: TruncCode): Integer; They both will return a hunk of text which will fit in the width specified and has the correct truncation symbol(internationally speaking). IM-Text 5-71 to 5-72 has the details. John Harvey +++++++++++++++++++++++++++ >From mgr@aggroup.aggroup.com (Mike Russell) Date: Thu, 10 Mar 1994 12:44:02 -0800 Organization: the ag group, inc. In article <1994Mar10.033524.1@cubldr.colorado.edu>, warwick_j@cubldr.colorado.edu wrote: > What is the best way to draw a Str255 into a Rect, abbreviating the > string if it doesn't fit by putting an ellipsis at the end? Here's some code that tries to use condensed text, then truncates the center of the string. - -- /* * shoehorn - shrink a name to the specified width by first setting condensed text * face, then deleting letters from the middle. Returns the value * of StringWidth(). Returns the final width. * * Face is not altered if it is already nonzero. */ int shoehorn(StringPtr name, int *face, int w) { int extra = (*face & italic)?CharWidth(' '):0; int ww; int elipsis = 0; Ptr p; while(name[0] > 1 && (ww=StringWidth(name) + extra) > w) { if(!name[0] || !w) return ww; if(!(*face & condense)) { TextFace(*face |= condense); } else { if(!elipsis) name[elipsis = name[0]/2] = 'É'; p = (Ptr)name + elipsis + 1; if(elipsis > name[0]/2) { p -= 2; elipsis--; } BlockMove(p+1, p, name[0] - (p - (Ptr)name)); name[0]--; } } return ww; } +++++++++++++++++++++++++++ >From harveyj@dunx1.ocs.drexel.edu. (harveyj) Date: Mon, 14 Mar 1994 16:08:54 GMT Organization: Drexel University, Office Of Computing Services In article B.Kobben@frw.ruu.nl (Barend Kobben) writes: > I have not got IM-Text (yet), but Trunctext and Truncstring aren't in Think > Reference either. Could this be correct? Anyway, do these functions work if > I want to offer sys 6 compatibility? I don't own a paper copy of IM-Text myself, but I'm getting by with copies on CD's that are lying around my place of work. Anyway, TruncText and TruncString are not available prior to 7.0 script manager. If you want to do the right thing internationally on systems earlier than 7.0 you need to dig the ellipsis character out of the 'itl4' resource's untoken table yourself and then measure your text to figure out where to put the ellipsis character. IM-Text has some example code for finding the token table and retrieving the desired character. Here it is (I know it is in Pascal, blame IM-Text not me): PROCEDURE MyMapTokenToString(theScript: ScriptCode; theToken: Integer; VAR theString: Str255); VAR itlHandle: Handle; untokenOffset: LongInt; untokenLength: LongInt; untokenPtr: UntokenTablePtr; untokenStringPtr: StringPtr; BEGIN GetIntlResourceTable(theScript, smUnTokenTable, itlHandle, untokenOffset, untokenLength); IF itlHandle = NIL THEN {handle errors, return null string} theString := '' ELSE BEGIN {make untokenPtr point to the } { beginning of the untoken table} untokenPtr := UntokenTablePtr(LongInt(itlHandle^) + untokenOffset); IF theToken > untokenPtr^.lastToken THEN {this token is } { not in table-- } theString := '' { return null string} ELSE BEGIN {index[theToken] is the offset } { of the desired string from the } { beginning of the untoken table} untokenStringPtr := StringPtr(LongInt(untokenPtr) +untokenPtr^.index[theToken]); theString := untokenStringPtr^; END; END; I'll leave the measuring code and inserting the character to the reader (there was another posting which provided code to do that, I think). Of course, if you don't mind the ellipsis character turning into a hiragana character on a Japanese system ( and other things on other non-roman systems), the easiest thing to do is just hardwire the ellipsis character. If you worry much about text on the Mac then IM-Text is a pretty important investment. Stuff that was scattered everywhere is finally together in one book, and questions about when features are available are easily answered. Sorry, I didn't include a mention of 6.0 compatibility before. John Harvey +++++++++++++++++++++++++++ >From Lars.Farm@nts.mh.se (Lars Farm) Date: Tue, 15 Mar 1994 10:43:13 +0100 Organization: Mid Sweden University In article <1994Mar14.160854.3349@netnews.noc.drexel.edu>, harveyj@dunx1.ocs.drexel.edu. (harveyj) wrote: > Anyway, TruncText and TruncString are not available prior to 7.0 > script manager. They were introduced in 6.0.3 or 6.0.4 I think, with Upr/LwrText and others in the script manager. Lars -- Lars.Farm@nts.mh.se +++++++++++++++++++++++++++ >From harveyj@dunx1.ocs.drexel.edu. (harveyj) Date: Tue, 15 Mar 1994 13:11:49 GMT Organization: Drexel University, Office Of Computing Services In article Lars.Farm@nts.mh.se (Lars Farm) writes: > They were introduced in 6.0.3 or 6.0.4 I think, with Upr/LwrText and others > in the script manager. I sound like a parrot with this IM-Text stuff, but table 6-1 on page 6-6 of IM-Text says that TruncText and TruncString were introduced with version 7.0 Script Manager. Version 7.0 Script Manager was first released with system 7.0 (table 6-2 page 6-9 of IM-Text). Like Al Smith said, "Let's look at the record." Of course, I've apparently lost my mind to quote somebody without a reference. But, I think I saw the quote in _Mad Magazine_, April 1964. OK? John Harvey --------------------------- >From klug@genesis.nred.ma.us (Mark Pirri) Subject: Finder comments on non-Desktop DB volumes? Date: Fri, 11 Mar 1994 05:14:07 GMT Organization: Genesis Public Access Unix +1 508 664 0149 Is it possible to read the Finder comments for files on a <2MB volume (i.e. no Desktop database) in System 7. I know that they're stored in the old-style Desktop file (resource type 'FCMT' or something like that), but since the Finder always keeps that open, how can I access them? Any assistance would be greatly appreciated. Thanks in advance -mark p -- - ------------------------------\ Mark N. Pirri \ THIS SPACE FOR RENT internet: klug@genesis.nred.ma.us \ no corny .sig's, please! AOL: TheVortex [@aol.com] \ +++++++++++++++++++++++++++ >From kd@summit.novell.com (Delbarre K.) Date: 11 Mar 1994 20:18:40 -0500 Organization: Novell, Summit In article klug@genesis.nred.ma.us (Mark Pirri) writes: >Is it possible to read the Finder comments for files on a <2MB volume >(i.e. no Desktop database) in System 7. I know that they're stored in the >old-style Desktop file (resource type 'FCMT' or something like that), but >since the Finder always keeps that open, how can I access them? [ ... ] You can open the Desktop resource file read-only using FSpOpenResFile(spec, fsRdPerm) or some variant thereof. TN212 says to avoid opening a resource file read-only, because it could lead to a corrupted resource map. If there is a safer alternative I'd love to hear about it. My utility GetInfo exists primarily to allow you to save and restore all of your comments from a System 7 Desktop Database, but also has the capability of extracting the comments from an old-style Desktop resource file. It uses FSpOpenResFile(spec, fsRdPerm) to open the resource file for the reason you mention. -- Kelvin Delbarre, Omicron Software Systems, Inc. contracted to Novell's UNIX System Laboratories, Summit, NJ kd@summit.novell.com +++++++++++++++++++++++++++ >From ldo@waikato.ac.nz (Lawrence D'Oliveiro, Waikato University) Date: 14 Mar 94 18:05:57 +1300 Organization: University of Waikato, Hamilton, New Zealand In article , klug@genesis.nred.ma.us (Mark Pirri) writes: > Is it possible to read the Finder comments for files on a <2MB volume > (i.e. no Desktop database) in System 7. I know that they're stored in the > old-style Desktop file (resource type 'FCMT' or something like that), but > since the Finder always keeps that open, how can I access them? Here's an idea I came up with. Unfortunately, it'll only work with Finder 7.1.3 (which makes proper use of the AppleEvent Manager): * Install a system handler for a custom AppleEvent. * Send this event to the Finder, so it executes your custom event handler in the Finder's process context. * Your custom handler now has full access to all the resource files the Finder has open, including the desktop database on <2MB volumes. Now, can anyone figure out how to make this work with pre-7.1.x Finders...? Lawrence (had a lot of fun with special kernel ASTs under VAX/VMS) +++++++++++++++++++++++++++ >From leonardr@netcom.com (Leonard Rosenthol) Date: Tue, 15 Mar 1994 20:03:10 GMT Organization: Aladdin Systems, Inc. In article <1994Mar14.180557.26363@waikato.ac.nz>, ldo@waikato.ac.nz (Lawrence D'Oliveiro, Waikato University) wrote: > Here's an idea I came up with. > Unfortunately, it'll only work with Finder 7.1.3 > (which makes proper use of the AppleEvent Manager): > > * Install a system handler for a custom AppleEvent. > * Send this event to the Finder, so it executes your custom event handler > in the Finder's process context. > * Your custom handler now has full access to all the resource files the Finder > has open, including the desktop database on <2MB volumes. > > Now, can anyone figure out how to make this work with pre-7.1.x Finders...? > Actually it will work JUST FINE under ANY version of System 7, since even older versions of the Finder will end up "forwarding" on the event to the system handlers. In fact, this is how OSA Menu works - it sends an event to the current process that should end up getting ignored and processed by my system handler. Leonard - ------------------------------------------------------------------------ Leonard Rosenthol Internet: leonardr@netcom.com Director of Advanced Technology AppleLink: MACgician Aladdin Systems, Inc. GEnie: MACgician --------------------------- >From ssiegler@hns.com (Stuart Sieger) Subject: Finding System Folder (Again) Date: Mon, 28 Feb 1994 18:54:49 GMT Organization: Hughes Network Systems Inc. OK, Im hopeless. I am trying to "find" the system folder so that I can put my preferences there... How does one go about that? I read that FindFolder works for sys7 only (and I still need to support sys6). Can someone give me a code frag (or point me in the right direction) to locate the system folder (or at least locate the path-string that leads to the folder (ie, disk:System Folder:Preferences). Any other suggestions (other than RTFM (I already tried that)) would be helpful. Stuart Siegler "Just because you're paranoid doesn't mean they aren't out to get you" +++++++++++++++++++++++++++ >From alana@cs.uoregon.edu (Alan Akins) Date: 3 Mar 1994 09:19:45 -0800 Organization: The uncharted backwaters of the unfashionable end of the Western Spiral arm of the Galaxy. In article <1994Feb28.185449.22632@hns.com>, Stuart Sieger wrote: > > I am trying to "find" the system folder so that I can put my > preferences there... > > How does one go about that? I read that FindFolder works for sys7 > only (and I still need to support sys6). Can someone give me > a code frag (or point me in the right direction) to locate the > system folder (or at least locate the path-string that leads > to the folder (ie, disk:System Folder:Preferences). OK. Using FindFolder with System 7 is all I can help you with. I know that glue code is supplied in THINK C for System 6 as well, but I've never tried anything I've written with pre Sys7 systems. FindFolder is doc'd in IM: Mac TB Essentials 7-54 thru 7-56 and is defined: FUNCTION FindFolder( vRefNum: Integer; folderType: OSType; createFolder: Boolean; VAR foundVRefNum: Integer; VAR foundDirID: LongInt): OSErr; The System Folder has constant type kSystemFolderType. For my example, we also depend on the system constants kOnSystemDisk and kCreateFolder. So, one would use it like this (in C): long FindSysFolder( void ) { long dirID; short vRefNum; OSErr err; err = FindFolder( kOnSystemDisk, kSystemFolderType, kCreateFolder, &vRefNum, &dirID ); if ( err == noErr ) return dirID; else /* Do some error recovery here */ ; } This will look for the System Folder on the startup disk and if it is not found, it will be created. Since it looks on the startup disk, it should definitely be able to find it! Hope this all helps! -- * "Evan's been doing parallel | Alan Akins * * processing for so long... | alana@cs.uoregon.edu * * he's beside himself." | University of Oregon * * - Me | Department of Computer Science * +++++++++++++++++++++++++++ >From Steve Bryan Date: Fri, 4 Mar 1994 06:20:56 GMT Organization: Sexton Software In article <1994Feb28.185449.22632@hns.com> Stuart Sieger, ssiegler@hns.com writes: > only (and I still need to support sys6). Can someone give me > a code frag (or point me in the right direction) to locate the > system folder (or at least locate the path-string that leads > to the folder (ie, disk:System Folder:Preferences). Call SysEnvirons. This sets a variable of type SysEnvRec. One of its fields is sysVRefNum which is a working directory refNum for the system folder. If you need its 'real' vRefNum and dirID use sysVRefNum and a call to PBGetWDInfo. Steve Bryan InterNet: sbryan@maroon.tc.umn.edu Sexton Software CompuServe: 76545,527 Minneapolis, MN Fax: (612) 929-1799 --------------------------- >From kurisuto@chopin.udel.edu (Sean J. Crist) Subject: Free code: Sean's window manager Date: 8 Mar 1994 20:07:11 -0500 Organization: University of Delaware Following is the Pascal code I mentioned on an earlier post; since a few people have expressed an interest, I'll go ahead and post it. This is basically an extension to the Window Manager with two functions: 1) it supports floating palettes associated with specific windows, and 2) it helps keep track of which window is which when your application allows the user to open any number of windows (e.g. if you're writing a word processor which allows any number of documents to be open at once, this code helps to tell the document windows apart from each other without maintaining a WindowPtr to each one). Sorry that this is isn't binhexed or compressed. This code may be freely incorporated into shareware programs, but I reserve all other rights. Military use of this code is specifically prohibited. unit SeansWindowManager; {Copyright 1994 by Sean Crist (kurisuto@chopin.udel.edu). This code may be freely incorporated into shareware} {or freeware projects. All other rights reserved.} {I am aware of no bugs in this code, but please send me reports of any bugs you find.} { What this code is for: This is basically an extension to the Window Manager 1) to support floating palettes, and} { 2) to obviate the need to keep WindowPtr's to each window. If you are writing an application with a fixed number} {of windows, you can just define your WindowPtr's as globals, but if your application supports arbitrary} {numbers of windows (e.g. a word processor which allows any number of documents to be open at a time), it can be} {a hassle to keep track of all of these WindowPtr's in a variable-length array or whatever. The following code} {makes it easy to manage large numbers of windows of assorted kinds. } { The basic strategy here is to put a handle in the RefCon of every window opened by your application (not only} {your 'document' windows but also your Clipboard window, your modeless dialogs, etc). This handle contains} {information uniquely identifying the window. You don't need to keep any pointers to specific windows; when you} {want a certain window, you just call one of the routines below, giving information to identify the window.} {The code below quickly looks through all the windows and gives you a pointer to the window you want.} { Of course, you need not be greatly concerned with these handles; just make the appropriate calls to the} {routines below, and most of the grubby work will be done for you.} {There's several changes you must make to your code, and to the code below, for this all to work properly:} {1. You must edit the list of wTypes below to reflect all the kinds of windows your program supports.} {2. You must edit the SetPrivateHilite routine below to reflect the relation between palettes and regular} { windows in a way specific to your application. For example, if you want your wToolsPalette to become} { visible when one of you wArtWindows is selected, you should code this here.} {3. Your program's initialization routine must set the PrivateFrontWindow global (declared below) to some} { valid WindowPtr. It doesn't matter which window this is, as long as it is a valid one. The code below} { will change the PrivateFrontWindow in response to your calls, but it needs a window to start out with.} {4. Every time you open a new window, you must call InitializeWindow on it to record what kind of window it is.} { Just before you dispose of a window, you must call DisposeWData on it first.} {5. You must not call the Toolbox routine SelectWindow, since this will mess up the hiliting of windows and } { visibility of palettes. Use the routine PrivateActivate (defined below) instead.} {6. In your event loop, you need to do a little extra work to support floating palettes. We treat a window and } { its palettes as one 'layer'. When you get a mousedown in PrivateFrontWindow, or in one of the palettes} { belonging to PrivateFrontWindow, then you should just call BringToFront on that window.} { (Your event code thus needs to be smart about what kinds of palettes belong to what kinds } { of windows.)} { If the mousedown is in some other window (i.e. neither PrivateFrontWindow nor its palettes), then you should} { call PrivateActivate, which is much like SelectWindow except that it does the extra work to support floating} { palettes and make sure everything gets hilited properly.} interface {Window types} const wMiscWindow = 1; wMiscWindowWithPalette = 2; wMiscPalette = 3; {These window types are just to illustrate how this code works. In your program, you would want to change these} {constants to whatever kinds of windows your program supports. (The application I'm working on has about 15} {different kinds of windows and three kinds of palettes, for example.) Each window type, including palettes, must} {have a unique identifying number.} const BadWindow = 9999; {For doing error checking. We send this to our own error handlers, pretending it's a real Toolbox error code.} var PrivateFrontWindow: WindowPtr; {This is the WindowPtr to the window that we _consider_ to be the front window, ignoring whatever floating palettes} {might be in front of it in the actual window list. Note: you must initialize this to some valid WindowPtr when your} {program initializes itself, or this code will crash.} {We store the following record as a handle in the RefCon field of a window. It contains all of our information that} {we need to keep track of what kind of window this is. Most of the time, you'll never need to manipulate the contents} {of this record directly, since there's more convenient routines below to do this work for you.} type WindowData = record Class: Integer; {What kind of window or dialog? This is one of the wType constants above.} Owner: Integer; Index: Integer; DataHandle: Handle; {Handle to whatever other data you wish to store for this window.} AuxData: Integer; {To be used however you like.} end; WDataPtr = ^WindowData; WDataHandle = ^WDataPtr; { Note on the fields 'Class', 'Owner', and 'Index': the Class is the kind of window, e.g. a Clipboard window,} {a search-and-replace modeless dialog, or whatever. This field contains one of the wType constants defined above.} {The owner and index tell which window of that kind we are talking about. In the case where there's only one } {instance of a kind of window (such as a Clipboard window), you can just set Owner and Index to 0 when you call } {InitializeWindow. When there's more than one instance of a particular window type, give each window a different } {Index to distinguish it.} { Under normal circumstances, you can just set Owner to 0 in all cases. I include this field because my application } {has script windows for different kinds of objects, so I need to know if this is, say, the script window for} {the 7th zone or the 7th room or whatever.} {Call InitializeWindow when you are opening a new window. You are responsible for creating the window with} {GetNewCWindow or GetNewDialog or whatever; pass this handle in WhichWindow. InitializeWindow allocates} {a WDataHandle, installs it in the refCon of whichWindow, and sets up the Class, Owner, and Index values.} function InitializeWindow (whichWindow: WindowPtr; Class, Owner, Index: Integer): Boolean; {Dispose the WDataHandle associated with whichWindow. Note: You are responsible for disposing whatever} {data you have stored in DataHandle. The right order to dispose things is: 1) dispose any data of your own} {which you've stored in DataHandle 2) call DisposeWData 3) dispose of the window or dialog itself with} {the appropriate Toolbox call.} procedure DisposeWData (whichWindow: WindowPtr); {Store this handle in DataHandle.} procedure SetWHandle (whichWindow: WindowPtr; TheHandle: Handle); {Return the handle stored in DataHandle.} function GetWHandle (whichWindow: WindowPtr): Handle; {Given a window, return its WDataHandle} function GetWData (whichWindow: WindowPtr): WDataHandle; {What is the class of whichWindow? (You could accomplish this same thing by calling GetWData and then} {looking at MyWData^^.Class, but this routine saves work.) Returns -1 if the WData is bad (i.e., you probably} {didn't call InitializeWindow on this window.} function GetWClass (whichWindow: WindowPtr): Integer; {What is the index of whichWindow? (You could accomplish this same thing by calling GetWData and then} {looking at MyWData^^.Index, but this routine saves work.) Returns -1 if the WData is bad (i.e., you probably} {didn't call InitializeWindow on this window.} function GetWIndex (whichWindow: WindowPtr): Integer; {Search through all the windows and try to find the one which has the specified class, owner, and index.} function SearchWindow (Class, Owner, Index: Integer): WindowPtr; {Same as SearchWindow, but for windows like the Clipboard which have only one instance.} function FindUniqueWindow (Class: Integer): WindowPtr; {Try to bring to front the window with this class, owner, and index. Returns TRUE if there is no such window,} {i.e. the window can't be activated and must be created. This can make your code succinct; when the user} {does some action to open a particular window, your routine MyOpenWindow can start out 'if CantActivate} {(the window I need) then (do whatever to open it, including calling InitializeWindow)'.} function CantActivate (Class, Owner, Index: Integer): Boolean; {You should use this instead of SelectWindow.} procedure PrivateActivate (whichWindow: WindowPtr); implementation procedure doOSErr (ErrorCode: Integer); begin {Handle the error however you like. I usually post an alert.} end; {Error checking. Make sure the WDataHandle is a valid one by checking its length. This is} {mainly for debugging.} function IsValidWindowHandle (TheWDataHandle: WDataHandle): Boolean; var HandleSize: LongInt; begin IsValidWindowHandle := TRUE; HandleSize := GetHandleSize(Handle(TheWDataHandle)); if HandleSize <> SizeOf(WindowData) then IsValidWindowHandle := FALSE; end; function GetWData (whichWindow: WindowPtr): WDataHandle; var thePeek: WindowPeek; TheHandle: Handle; begin if WhichWindow = nil then begin doOSErr(BadWindow); GetWData := nil; end else begin thePeek := WindowPeek(WhichWindow); TheHandle := Handle(thePeek^.RefCon); GetWData := WDataHandle(TheHandle); end; end; function GetWClass (whichWindow: WindowPtr): Integer; var WData: WDataHandle; begin WData := GetWData(whichWindow); if IsValidWindowHandle(WData) then GetWClass := WData^^.Class else GetWClass := -1; end; function GetWIndex (whichWindow: WindowPtr): Integer; var WData: WDataHandle; begin WData := GetWData(whichWindow); if IsValidWindowHandle(WData) then GetWIndex := WData^^.Index else GetWIndex := -1; end; function GetWHandle (whichWindow: WindowPtr): Handle; var WData: WDataHandle; begin WData := GetWData(whichWindow); if IsValidWindowHandle(WData) then GetWHandle := WData^^.DataHandle else begin GetWHandle := nil; doOSErr(BadWindow); end; end; procedure SetWHandle (whichWindow: WindowPtr; TheHandle: Handle); var WData: WDataHandle; begin WData := GetWData(whichWindow); if IsValidWindowHandle(WData) then WData^^.DataHandle := TheHandle else doOSErr(BadWindow); end; function InitializeWindow (whichWindow: WindowPtr; Class, Owner, Index: Integer): Boolean; var thePeek: WindowPeek; WData: WDataHandle; OkSoFar: Boolean; Result: Integer; begin OkSoFar := true; thePeek := WindowPeek(WhichWIndow); WData := WDataHandle(NewHandle(SizeOf(WindowData))); Result := MemError; if Result <> 0 then begin OkSoFar := False; doOSErr(MemError); end; if OkSoFar then begin thePeek^.RefCon := LongInt(WData); WData^^.Class := Class; WData^^.Owner := Owner; WData^^.Index := Index; end; InitializeWindow := OkSoFar; end; procedure DisposeWData (whichWindow: WindowPtr); var WData: WDataHandle; begin WData := GetWData(whichWindow); if IsValidWindowHandle(WData) then DisposHandle(Handle(WData)) else doOSErr(BadWindow); end; {I hope this is still a kosher way to find out which window is really in the front! If this is no longer} {kosher, then I'd just make an invisible window which is always frontmost (a la BringToFront) and} {use it as my starting point for the search through the linked list.} function findFrontWindow: WindowPtr; const WindowList = $9D6; type PtrPtr = ^Ptr; var WindowListPtr: PtrPtr; begin WindowListPtr := Pointer(WindowList); findFrontWindow := WindowPtr(WindowListPtr^); {was: FrontWindow} end; function SearchWindow (Class, Owner, Index: Integer): WindowPtr; var done: boolean; ThisWindow, FoundWindow: WindowPtr; WData: WDataHandle; ThisWPeek: WindowPeek; begin done := false; FoundWindow := nil; ThisWindow := FindFrontWindow; if ThisWindow <> nil then while not done do begin WData := GetWData(ThisWindow); if IsValidWindowHandle(WData) then if WData^^.Class = Class then if WData^^.Owner = Owner then if WData^^.Index = Index then begin FoundWindow := ThisWindow; Done := true; end; if not Done then begin ThisWPeek := WindowPeek(ThisWindow); ThisWPeek := ThisWPeek^.nextWindow; ThisWindow := WindowPtr(ThisWPeek); if ThisWindow = nil then Done := true; end; end; SearchWindow := FoundWindow; end; function CantActivate (Class, Owner, Index: Integer): Boolean; var ThisWindow: WindowPtr; begin CantActivate := TRUE; {Assume the window doesn't exist.} ThisWindow := SearchWindow(Class, Owner, Index); if ThisWindow <> nil then begin SelectWindow(ThisWindow); CantActivate := FALSE; {The window exists, so we _can_ activate it.} end; end; function FindUniqueWindow (Class: Integer): WindowPtr; begin FindUniqueWindow := SearchWindow(Class, 0, 0); {By convention, all unique windows have 0 and 0 as their other arguments.} end; procedure AutoPositionPalettes (WhichWindow: WindowPtr); begin {If you want your palettes to be automatically positioned next to a certain kind of window, put code here} {to move the palettes to the right position.} end; {This internal routine is used to hilite or unhilite windows. Note that there's more going on here than} {just drawing the hiliting on the window. For our purposes, 'hilite' means 'bring it to the front, hilite it,} {and display its palettes as well'. 'Unhilite' means 'Turn off its hiliting, and hide its palettes also.'} procedure SetPrivateHilite (whichWindow: WindowPtr; Hilite: Boolean); begin if WhichWindow = nil then doOSErr(BadWindow); if Hilite then begin BringToFront(whichWindow); ShowHide(whichWindow, TRUE); end; HiliteWindow(whichWindow, Hilite); {If this window has a palette, bring it to the front as well.} case GetWClass(whichWindow) of {You should modify the case selectors here to handle whatever kinds of windows with palettes your application supports.} wMiscWindowWithPalette: begin if Hilite then begin AutoPositionPalettes(whichWindow); BringToFront(FindUniqueWindow(wMiscPalette)); end; ShowHide(FindUniqueWindow(wMiscPalette), Hilite); end; end; end; {Since we're using windows in a slightly unorthodox way, we can't rely on the Activate and Deactivate events} {to do our work for us. doSendPrivateActivateMessage is the routine to handle our equivalent of an Activate} {event for the PrivateFrontWindow. (Palettes can never be the PrivateFrontWindow, by definition.)} procedure doSendPrivateActivateMessage (whichWindow: WindowPtr); external; procedure privateActivate (whichWindow: WindowPtr); begin SetPrivateHilite(PrivateFrontWindow, FALSE); PrivateFrontWindow := whichWindow; SetPrivateHilite(PrivateFrontWindow, TRUE); {Then send a message to update menus, etc.} doSendPrivateActivateMessage(PrivateFrontWindow); end; end. --------------------------- >From grantd@dcs.gla.ac.uk (Dair Grant) Subject: How does the Finder handle events? Date: Wed, 9 Mar 1994 16:46:06 GMT Organization: Glasgow University Computing Science Dept. How does the Finder handle the high level Apple Events listed in its 'fmnu' resources? I've sat in the event queue and watched the same events arriving from other applications as expected, but the Finder doesn't appear to send anything to itself for the same event (e.g., 'sdup'). I've also tried installing new handlers to override any original handlers, but they're never actually called - in fact, they don't actually get to override anything, as there don't seem to be any handlers installed which they can override. What mechanism does the Finder use for handling these AEs? How do things like CopyDoubler intercept control? Any ideas? -dair +++++++++++++++++++++++++++ >From hubauer@telerama.lm.com (Bill Hubauer) Date: 10 Mar 1994 08:24:35 -0500 Organization: Telerama Public Access Internet, Pittsburgh, PA Dair Grant (grantd@dcs.gla.ac.uk) wrote: : : How does the Finder handle the high level Apple Events listed in its : 'fmnu' resources? I've sat in the event queue and watched the same events : arriving from other applications as expected, but the Finder doesn't : appear to send anything to itself for the same event (e.g., 'sdup'). : : I've also tried installing new handlers to override any original handlers, : but they're never actually called - in fact, they don't actually get to : override anything, as there don't seem to be any handlers installed which : they can override. : : What mechanism does the Finder use for handling these AEs? How do things : like CopyDoubler intercept control? Any ideas? : : : : -dair The non-scriptable finder does not use the apple event manager at all. It just uses highlevel events and parses them without the help of the apple event manager. This is why you can't patch in. -- - ------------------------------------------- Bill Hubauer Hubauer@TeleRama.pgh.pa.us AOL: MacBilly CIS: 76114,3012 +++++++++++++++++++++++++++ >From gurgle@netcom.com (Pete Gontier) Date: Thu, 10 Mar 1994 17:45:01 GMT Organization: cellular hubauer@telerama.lm.com (Bill Hubauer) writes: >Dair Grant (grantd@dcs.gla.ac.uk) wrote: >: How does the Finder handle the high level Apple Events listed in its >: 'fmnu' resources? I've sat in the event queue and watched the same >: events arriving from other applications as expected, but the Finder >: doesn't appear to send anything to itself for the same event (e.g., >: 'sdup'). >: >: I've also tried installing new handlers to override any original >: handlers, but they're never actually called - in fact, they don't >: actually get to override anything, as there don't seem to be any >: handlers installed which they can override. >: >: What mechanism does the Finder use for handling these AEs? How do >: things like CopyDoubler intercept control? Any ideas? >The non-scriptable finder does not use the apple event manager at all. >It just uses highlevel events and parses them without the help of the >apple event manager. This is why you can't patch in. However, note that half of his investigations, he says, have been with the event queue, not with the AppleEvent Manager. It would be interesting to hear whether he is watching event records as they come back from WNE or if he is waiting for Finder to call some other trap to clue him in that there might be a high level event or AppleEvent being handled. If the former, it sounds like Finder does not even defer its event processing until the next iteration of the event loop. This would not be surprising if Finder used AppleEvents, because the AE Manager routes events sent to self directly to the handler. But we know Finder is not using the AE Manager, so it might be that it sends high level events to itself and somehow waits for the event loop to process them. Then again, it might not. More information is in order. Oh, MacsBug... ATB A88F rA7^.w==34 ...which puts a break on PostHighLevelEvent, which is probably what Finder would be using instead of AESend. Although it does get called when Finder wants to open a document into a running app ('odoc' -- probably it's just the AE manager calling PostHighLevelEvent rather than Finder), it doesn't get called when one makes a Finder menu selection or drags an icon from one folder to another. However, doing little investigations like this one is the very essence of this sort of hack. Be persistent, and good luck. -- Pete Gontier, CTO, Integer Poet Software; gurgle@netcom.com --------------------------- >From dubois@uakari.primate.wisc.edu (Paul DuBois) Subject: How to determine color of progress bar? Date: 9 Mar 1994 23:05:40 -0600 Organization: Castra Parvulorum When the Finder does a copy, it shows a progress bar. How do I tell what the background and foreground colors of the bar are? -- Paul DuBois dubois@primate.wisc.edu +++++++++++++++++++++++++++ >From kenlong@netcom.com (Ken Long) Date: Thu, 10 Mar 1994 08:47:42 GMT Organization: NETCOM On-line Communication Services (408 241-9760 guest) Do you want to tell what color they are, or make them be a certain color? The gray is RGB 17476, and the lavender is R 52428, G 52428, B 65535. Kinda hard to screen shot it while a dialog's cookin', huh. The above numbers are from Joe Zobkiw's "Finder Prgress", which should also jive with Scott Knaster's "erasing your hard disk" SMP demo. -Ken- +++++++++++++++++++++++++++ >From kenlong@netcom.com (Ken Long) Date: Thu, 10 Mar 1994 15:41:03 GMT Organization: NETCOM On-line Communication Services (408 241-9760 guest) That's "MPS" - not SMP. ("club" finger, late night, craniaplegic, no glasses, keyboard worn out, etc.) Mac Programming Secrets C source - dig? -Ken- +++++++++++++++++++++++++++ >From rmcassid@uci.edu (Robert Cassidy) Date: Thu, 10 Mar 1994 10:24:22 -0700 Organization: TLG Project In article , kenlong@netcom.com (Ken Long) wrote: > Do you want to tell what color they are, or make them be a certain color? > > The gray is RGB 17476, and the lavender is R 52428, G 52428, B 65535. > > Kinda hard to screen shot it while a dialog's cookin', huh. > > The above numbers are from Joe Zobkiw's "Finder Prgress", which should > also jive with Scott Knaster's "erasing your hard disk" SMP demo. > > -Ken- Does the progress bar vary it's colors according to the Color control panel the way windows do? (I'd check, but I have a *%&$@# monochrome monitor) I've only looked at windows and controls but these two have optional color tables or system default color tables (based on Color control panel settings) that contain the proper values. Look at Troy Gaul's Infinity Windoid code. His code can show you what to do for black and white as well as color - very helpful. -- Robert Cassidy TLG Project UC Irvine Let's hope 'Information SuperTollroad' isn't the catchphrase of the next decade... +++++++++++++++++++++++++++ >From mgr@aggroup.aggroup.com (Mike Russell) Date: Thu, 10 Mar 1994 12:40:57 -0800 Organization: the ag group, inc. In article <2lm9r4INNj2v@uakari.primate.wisc.edu>, dubois@uakari.primate.wisc.edu (Paul DuBois) wrote: > When the Finder does a copy, it shows a progress bar. How do > I tell what the background and foreground colors of the bar are? I use shades of the user's select color, as someone suggested long ago in this news group. That way you use a color that the user chose and presumably likes. +++++++++++++++++++++++++++ >From kenlong@netcom.com (Ken Long) Date: Fri, 11 Mar 1994 01:25:27 GMT Organization: NETCOM On-line Communication Services (408 241-9760 guest) So how do you get the colors the user set with the Colors Control Panel? Greg's buttons taps those, too. I wasn't aware the progress colors change along with it. I'll have to see that for myself. (Oh goody! Something else to do on my Mac!) -Ken- +++++++++++++++++++++++++++ >From troy@i-link.com (Troy Gaul) Date: 11 Mar 1994 00:35:51 -0600 Organization: I-Link, Ltd., Des Moines, IA, USA - 515/255-2754 In article , Ken Long wrote: >So how do you get the colors the user set with the Colors Control Panel? >Greg's buttons taps those, too. If you get the Infinity Windoid WDEF and look in the Windoid Util file, there's a routine that gets a color from the window color table and sets it as the fore (or back) color. For example, do a: WctbForeColor(nil, wTingeLight); [The nil is the window parameter, you could pass in the WindowPtr, but if you use nil, it'll just use the default color table from the System.] With the standard window colors, this maps to the steel blue that we all know and love. With another tinge color, it maps to the appropriate shade of that tinge. >I wasn't aware the progress colors change along with it. I'll have to >see that for myself. (Oh goody! Something else to do on my Mac!) They don't. I've always thought this was a little odd. Actually, I've tried doing a progress bar that uses the tinge color, but it doesn't always look great (some of those tinge colors don't work well in that large of an area). _troy -- //////// ////// Troy Gaul t-gaul@i-link.com // // // I-Link, Ltd. // // // // "Iungo ergo sum." (I-Link, therefore I am.) // // ////// __________________________________________________________ // +++++++++++++++++++++++++++ >From kenlong@netcom.com (Ken Long) Date: Fri, 11 Mar 1994 09:06:30 GMT Organization: NETCOM On-line Communication Services (408 241-9760 guest) Thanks for that info, Troy. I'll have to get that WDEF out and thoroughly read it, and read up on it! -Ken- "I love it when a plan comes together." George Peppard as "Hannibal Smith" +++++++++++++++++++++++++++ >From jwbaxter@olympus.net (John W. Baxter) Date: Fri, 11 Mar 1994 12:58:24 -0800 Organization: Internet for the Olympic Peninsula In article , mgr@aggroup.aggroup.com (Mike Russell) wrote: > I use shades of the user's select color, as someone suggested long > ago in this news group. That way you use a color that the user chose > and presumably likes. As a user, I really wish you wouldn't (although for progress bars it's not so bad). AppleScript Script Editor has "forced" me to use a neutral grey for my highlight color, because it wants to use a shade of my highlight for the frame of its script editing window (monitor in 16-color mode). With a highly visible highlight color, the result is bizarre. -- John Baxter Port Ludlow, WA, USA [West shore, Puget Sound] jwbaxter@pt.olympus.net +++++++++++++++++++++++++++ >From kenh@world.std.com (Ken Hancock) Date: Sat, 12 Mar 1994 01:11:19 GMT Organization: Isle Systems - Nashua, NH In article <2lp3g7$l1p@ilink1.i-link.com>, Troy Gaul wrote: >In article , Ken Long wrote: >>I wasn't aware the progress colors change along with it. I'll have to >>see that for myself. (Oh goody! Something else to do on my Mac!) > >They don't. I've always thought this was a little odd. Actually, I've >tried doing a progress bar that uses the tinge color, but it doesn't >always look great (some of those tinge colors don't work well in that >large of an area). This is one of the things which makes me think that the window color control panel was a (good) hack by one of the engineeers who couldn't stand the "standard" purple. Personally, I've always done my progress bars using wTingeLight as Apple should have, IMHO. (It loes look silly having everything else in the window gold or green but still have that $#*& progress bar be purple) Ken -- Ken Hancock | INTERNET: kenh@vgi.com Isle Systems | Compuserve: >INTERNET: kenh@vgi.com Macintosh Consulting | AOL: KHancock | Disclaimer: My opinions are mine, +++++++++++++++++++++++++++ >From markhanrek@aol.com (MarkHanrek) Date: 12 Mar 1994 04:54:01 -0500 Organization: America Online, Inc. (1-800-827-6364) Do a cmd-shift-3 to take a snapshot of the screen while the progress dialog is up, then use the eyedropper tool of any color graphics editing / paint program to determine the RGB value or the indexed color value. Mark Hanrek +++++++++++++++++++++++++++ >From kenlong@netcom.com (Ken Long) Date: Sat, 12 Mar 1994 19:14:30 GMT Organization: NETCOM On-line Communication Services (408 241-9760 guest) I don't know if it happens in every instance, but, usually, when there's some operation going on and you try to do a screen shot, the command to do the screen shot goes on the "waiting list" and is carried out after the current operation is complete. Sometimes you can sneak a screenshot in if the operation is operating in a loop and checks for events (like the ones that look for keyDowns like Command-. etc.). But those colors are pretty easy to spot in a system color palette, in ResEdit or a color paint program - especially after seeing them several times a day, 7 days a week, for 2 (?) years. -Ken- +++++++++++++++++++++++++++ >From D.A.G.Gillies@bradford.ac.uk (David Gillies) Date: Mon, 14 Mar 1994 17:57:47 GMT Organization: Unseen University, Ankh-Morpork In article rmcassid@uci.edu (Robert Cassidy) writes: >In article , kenlong@netcom.com (Ken Long) >wrote: > >> Do you want to tell what color they are, or make them be a certain color? >> >> The gray is RGB 17476, and the lavender is R 52428, G 52428, B 65535. >> >> Kinda hard to screen shot it while a dialog's cookin', huh. >> >> The above numbers are from Joe Zobkiw's "Finder Prgress", which should >> also jive with Scott Knaster's "erasing your hard disk" SMP demo. >> >> -Ken- > >Does the progress bar vary it's colors according to the Color control panel >the way windows do? (I'd check, but I have a *%&$@# monochrome monitor) >I've only looked at windows and controls but these two have optional color >tables or system default color tables (based on Color control panel >settings) that contain the proper values. Look at Troy Gaul's Infinity >Windoid code. His code can show you what to do for black and white as well >as color - very helpful. If it's any help, the lilac colour is no. 42 in the standard system palette. I implement the progress bar by just having the system palette in my application and calling PmForeColor(42). Maybe not very elegant, but hey, it works. ______________________________________________________________________ David A. G. Gillies (D.A.G.Gillies@bradford.ac.uk) (c) 1994 Wittgenstein and The Furniture Depository of The Living Dead A little learning is a dangerous thing - but not half as dangerous as a lot of ignorance. - ---------------------REPLIES VIA EMAIL PLEASE----------------------- _/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ +++++++++++++++++++++++++++ >From walrathw@rferl.org (WalrathW) Date: 14 Mar 94 15:31:56 -0500 Organization: RFE/RL Inc. In article <2ls3fp$qta@search01.news.aol.com> markhanrek@aol.com (MarkHanrek) writes: > Do a cmd-shift-3 to take a snapshot of the screen while the progress dialog is > up, then use the eyedropper tool of any color graphics editing / paint program > to determine the RGB value or the indexed color value. > > Mark Hanrek > I should also point out a very useful set of FKEYs called Jon's FKEYs which I use all the time. There is one which lets you get the color of any pixel on the screen (in RGB, HSV, or CMY), and another which lets you drag out a rect of marching ants and gives you the coordinates. I use them all the time for determining what the cool colors other developers are using in their hacks are. They're available at the usual Mac archive sites. ________oOo________ Wayne Walrath RFE/RL Inc. walrathW@rferl.org +++++++++++++++++++++++++++ >From zobkiw@datawatch.com (joe zobkiw) Date: Tue, 15 Mar 1994 12:29:12 GMT Organization: Datawatch Corporation In article <1994Mar14.153157.371@dcvaxb.rferl.org>, walrathw@rferl.org (WalrathW) wrote: Forget it...use this routine...this will return the light and dark tinges currently being used by the WDEF/CDEF in System 7 to draw things like scroll bars and window borders, etc. You can then use these colors to draw the foreground and background of your progress bar. This way, you will always match what the user has selected in the Color control panel. And NO you shouldn't release the resource. Try it and you'll see why :) /******************************************************************************* GetWindowTinges Should have color quickdraw for this routine to be called *******************************************************************************/ void GetWindowTinges(RGBColor *lightTinge, RGBColor *darkTinge) { CTabHandle windowCTable; lightTinge->red = lightTinge->green = lightTinge->blue = 0xffff; darkTinge->red = darkTinge->green = darkTinge->blue = 0x0000; if ((windowCTable = (CTabHandle)GetResource('wctb', 0)) != nil) { *lightTinge = (**windowCTable).ctTable[11].rgb; *darkTinge = (**windowCTable).ctTable[12].rgb; } /* case for black and white window defs under system 7, both return black! */ if ((lightTinge->red == 0x0000) && (lightTinge->green == 0x0000) && (lightTinge->blue == 0x0000)) lightTinge->red = lightTinge->green = lightTinge->blue = 0xffff; } ___________________________________________________________ _/_/_/_/ Joe Zobkiw ,,, _/ Senior Software Engineer - - _/ Datawatch Corporation L _/_/_/_/ zobkiw@datawatch.com - +++++++++++++++++++++++++++ >From KLUEV@jonathan.srcc.msu.su Date: Wed, 16 Mar 1994 21:06:43 +0300 Organization: (none) In article zobkiw@datawatch.com (joe zobkiw) writes: >In article <1994Mar14.153157.371@dcvaxb.rferl.org>, walrathw@rferl.org >(WalrathW) wrote: > >Forget it...use this routine...this will return the light and dark tinges >currently being used by the WDEF/CDEF in System 7 to draw things like >scroll bars and window borders, etc. You can then use these colors to draw >the foreground and background of your progress bar. This way, you will >always match what the user has selected in the Color control panel. > >And NO you shouldn't release the resource. Try it and you'll see why :) > ... Code deleted ... > if ((windowCTable = (CTabHandle)GetResource('wctb', 0)) != nil) { > *lightTinge = (**windowCTable).ctTable[11].rgb; > *darkTinge = (**windowCTable).ctTable[12].rgb; ... It's better to use GetAuxWin procedure. This way you will take into account custom 'wctb's. Michael Kluev. +++++++++++++++++++++++++++ >From rollin@newton.apple.com (Keith Rollin) Date: Sun, 13 Mar 1994 01:32:55 GMT Organization: Apple Computer, Inc. In article <2ls3fp$qta@search01.news.aol.com>, markhanrek@aol.com (MarkHanrek) wrote: > Do a cmd-shift-3 to take a snapshot of the screen while the progress dialog is > up, then use the eyedropper tool of any color graphics editing / paint program > to determine the RGB value or the indexed color value. A neat idea, but not the best way to go. The color specified by the program drawing the progress bar (e.g., the Finder) is not necessarily the one that appears on the screen. Instead, the RGB color specified is mapped to the closest available color in the screen device's color table. To look at an extreme example, if the screen is in B&W mode, a nice purple will get mapped to black. Even on a 256 color device, the color specified will almost always be different than that displayed. When I was working on "Macintosh Programming Secrets", I wanted to get the *exact* colors that the Finder was using. To do this, I set breakpoints on a few of QuickDraw's calls (like PaintRect and FillCRect). I can't remember exactly what call the Finder was using, but when I broke into the debugger, I was able to either look at the color being passed into the call, or the RGBForeColor in the current CGrafPort. - -------------------------------------------------------------------------- Keith Rollin --- Phantom Programmer --- Apple Computer, Inc. --- Team Newton +++++++++++++++++++++++++++ >From melissa@i-link.com (Melissa Gaul) Date: Wed, 16 Mar 1994 18:41:48 -0600 Organization: I-Link, Ltd. In article <862D4F21C8@VADIK.srcc.msu.su>, KLUEV@jonathan.srcc.msu.su wrote: > In article > zobkiw@datawatch.com (joe zobkiw) writes: > >In article <1994Mar14.153157.371@dcvaxb.rferl.org>, walrathw@rferl.org > >(WalrathW) wrote: > > > >Forget it...use this routine...this will return the light and dark tinges > >currently being used by the WDEF/CDEF in System 7 to draw things like > >scroll bars and window borders, etc. You can then use these colors to draw > >the foreground and background of your progress bar. This way, you will > >always match what the user has selected in the Color control panel. > > > >And NO you shouldn't release the resource. Try it and you'll see why :) > > > ... Code deleted ... > > if ((windowCTable = (CTabHandle)GetResource('wctb', 0)) != nil) { > > *lightTinge = (**windowCTable).ctTable[11].rgb; > > *darkTinge = (**windowCTable).ctTable[12].rgb; > ... > > It's better to use GetAuxWin procedure. This way you will take into > account custom 'wctb's. If you do this, you should also be prepared in case the window's color table (from GetAuxWin) isn't long enough to hold the tinge colors you're looking for. Then, you could try GetAuxWin(nil) and try there, but this might still not have enough, so you should have some built-in defaults. (This all assumes you want to handle all cases. If you control the windows in your application and know this isn't needed, you might be able to avoid it.) _troy ////////_//////___Troy Gaul_________________________t-gaul@i-link.com___// // // I-Link, Ltd. // // // // "Iungo ergo sum." (I-Link, therefore I am.) // //____//////_________________________________________________________// +++++++++++++++++++++++++++ >From giles@med.cornell.edu (Aaron Giles) Date: Wed, 16 Mar 1994 22:12:52 -0500 Organization: Cornell University Medical College In article , rollin@newton.apple.com (Keith Rollin) wrote: > In article <2ls3fp$qta@search01.news.aol.com>, markhanrek@aol.com > (MarkHanrek) wrote: > >> Do a cmd-shift-3 to take a snapshot of the screen while the progress dialog is >> up, then use the eyedropper tool of any color graphics editing / paint program >> to determine the RGB value or the indexed color value. > > A neat idea, but not the best way to go. The color specified by the program > drawing the progress bar (e.g., the Finder) is not necessarily the one that > appears on the screen. Instead, the RGB color specified is mapped to the > closest available color in the screen device's color table. Of course, if you do this on a 24-bit color screen, you don't need to worry. :-) If you want your progress bars to look like the Finder's, try: static RGBColor gBarBackground = { 0xcccc, 0xcccc, 0xffff }; static RGBColor gBarForeground = { 0x6666, 0x6666, 0x6666 }; Assuming that "background" refers to the steel blue, and "foreground" refers to the gray. Aaron -- Aaron Giles Macintosh & Newton Developer Cornell University Medical College giles@med.cornell.edu +++++++++++++++++++++++++++ >From troy@i-link.com (Troy Gaul) Date: Thu, 17 Mar 1994 00:02:56 -0600 Organization: I-Link, Ltd. >In article , melissa@i-link.com >(Melissa Gaul) wrote: Oops, that was supposed to be me, not my wife. :( Just goes to show how a mechanism for having different preferences files for two people who use the same machine can be important, I guess... _troy ////////_//////___Troy Gaul_________________________t-gaul@i-link.com___// // // I-Link, Ltd. // // // // "Iungo ergo sum." (I-Link, therefore I am.) // //____//////_________________________________________________________// +++++++++++++++++++++++++++ >From arentz@batcave.knoware.nl (Stefan Arentz) Date: Thu, 17 Mar 1994 17:15:57 GMT Organization: Knoware In article , rollin@newton.apple.com (Keith Rollin) wrote: > When I was working on "Macintosh Programming Secrets", I wanted to get the > *exact* colors that the Finder was using. To do this, I set breakpoints on > a few of QuickDraw's calls (like PaintRect and FillCRect). I can't remember > exactly what call the Finder was using, but when I broke into the debugger, > I was able to either look at the color being passed into the call, or the > RGBForeColor in the current CGrafPort. RGBColor CProgressIndicator::mBlack = { 0x0000, 0x0000, 0x0000 }; RGBColor CProgressIndicator::mWhite = { 0xFFFF, 0xFFFF, 0xFFFF }; RGBColor CProgressIndicator::mDarkGrey = { 0x4000, 0x4000, 0x4000 }; RGBColor CProgressIndicator::mSteelBlue = { 0xCCCC, 0xCCCC, 0xFFFF }; Black is black, White is white, SteelBlue is the background color of the indicator, and DarkGray is the color of the moving bar... Great Book Keith! ;-) > ---------------------------------------------------------------------------- > Keith Rollin --- Phantom Programmer --- Apple Computer, Inc. --- Team Newton Er, Team Newton? Does this mean we can expect a 'Newton Programming Secrets'? -- Stefan - ----------------------------------------------------------------------- Stefan Arentz -- Lunatech Software Development -- arentz@knoware.nl +++++++++++++++++++++++++++ >From mshields%peruvian.cs.utah.edu@cs.utah.edu (Michael S Shields) Date: 17 Mar 94 16:25:05 MST Organization: University of Utah Computer Science Um, I just did a little test and I found that the progress bar in a finder copy doesn't depend on the window cor. I usually have my windws at the "Standard" color, so I switched it to red and the progress bar was still in the dark grey/ purplish color combo. So, I think that putting up a progress bar in the window colors might be unnerving to a user if you are trying to mimic the Finder. Also, it's work you could eliminate to spend more time on other things. Mike mshields@peruvian.cs.utah.edu mshields@dayna.com --------------------------- >From peloy@ccxbbs.uunet.ve Subject: How to draw inits icons? Date: 2 Mar 1994 07:35:11 -0600 Organization: Caracas Computer Exchange BBS To: comp-sys-mac-programmer@cs.utexas.edu Hello there. I've looking so far to find how to draw my INIT's icon on the bottom of the screen at boot time. I haven't found anything in Inside Macintosh or in the Technical Notes. I would like to know how can I do this. I could borrow the code needed to draw the icon from any INIT but I would like to understand how it works. When doing "reverse engineering" on the code to draw INIT's icons, I've found some low memory variables that are not documented. It would be very fine if you can send me source code to do this or you can explain me how to do my own code. I don't have direct access to c.s.m.p. so please send your help to my electronic address (peloy@ccxbbs.uunet.ve). Thans a lot in advance, Eloy A. Paris -> Alice4Mac 2.2.2E QWK Ser#127-1073 +++++++++++++++++++++++++++ >From kenlong@netcom.com (Ken Long) Date: Wed, 2 Mar 1994 16:58:26 GMT Organization: NETCOM On-line Communication Services (408 241-9760 guest) There's a couple files you can get. Connect to: ftp bigbird.csd.scarolina.edu and in the pub/mac directory is Jim Walker's "ShowIcon7" - a C project and info on doing that. Then, in alt.sources.mac is a file I got off AOL that is a C project for generic control panels and INITs which use "ShowINIT.c" to show it. I tried the example CP in this file and it did, indeed, show its icon on startup. The file is probably on sumex, as well. -Ken- --------------------------- >From dat91jre@ludat.lth.se (Regmyr Jonas) Subject: How to tell a Mac from a Mac? Date: 7 Mar 1994 08:49:33 GMT Organization: Lund Institute of Technology, Sweden Hi! Is there a way to tell one Mac from anotherone or, is there a way for a program to tell if it has been moved from one machine to anotherone, possible the same type (from, say, one Classic to another)? If so, how do I do this? I've thought about some ways to achive this: If there is a way to get the serial # of the machine the problem is solved (probably won't work). One could use the name of the boot volume but, what if the user change it -> program will get confused (not so nice approach). If there is a way to write to ROM there is a way to check the appearance of some word, bit or whatever and by that know if I've (the program) been here before (can one do this?). For me, this problem is yet to be solved. Please help me. Thanx... /Jonas... -- Mail: Karl Jonas Regmyr Carl Hillsgatan 9 S-217 56 Malmoe Sweden Phone: +46 (0)40 91 42 41 Email: dat91jre@ludat.lth.se +++++++++++++++++++++++++++ >From d88-jwa@mumrik.nada.kth.se (Jon Wätte) Date: 7 Mar 1994 11:02:09 GMT Organization: Royal Institute of Technology, Stockholm, Sweden In <2lepqt$1g3@nic.lth.se> dat91jre@ludat.lth.se (Regmyr Jonas) writes: >Is there a way to tell one Mac from anotherone or, is there a way >for a program to tell if it has been moved from one machine to >anotherone, possible the same type (from, say, one Classic to another)? Yes; write your program to require an ADB dongle; thus if your user moves the application but not the dongle (hardware key) your app will notice it has been moved. Copy protection in evil. >If there is a way to get the serial # of the machine the problem Nope. >One could use the name of the boot volume but, what if the user > change it -> program will get confused (not so nice approach). Very bad; users switch between systems daily for things like System 6 or Kanji or whatever. >If there is a way to write to ROM there is a way to check the > appearance of some word, bit or whatever and by that know if > I've (the program) been here before (can one do this?). ROM == Read-Only Memory == not-writable. The simplest thing you can do is to check if your preferences file is there in the preferences folder; if it's not, it's probably a new installation (or the user installed a new system or restored a backup, or switched systems or whatever) -- -- Jon W{tte, h+@nada.kth.se, Mac Hacker Deluxe -- This article printed on 100% recycled electrons. +++++++++++++++++++++++++++ >From Matt Slot Date: 7 Mar 1994 11:45:09 GMT Organization: University of Michigan Regmyr Jonas, dat91jre@ludat.lth.se writes: >Is there a way to tell one Mac from another one or, is there a way >for a program to tell if it has been moved from one machine to >anotherone, possible the same type (from, say, one Classic to another)? >If so, how do I do this? - ----------- First a note: dont make self-modifying apps! Your app should not store machine specific information within itself; if you save a preference do it to a preferences file. OK, off the podium. If you still need to identify a Mac from another, use the Volume Creation date for VRefNum = -1. This is the long date to the second of the initialization of that HD. For a 1 in 4 billion chance of duplication, this works rather well. If the user *does* reformat the boot disk, it will probably be a full reinstall and for all intents a "new" machine. Matt +++++++++++++++++++++++++++ >From u9119523@sys.uea.ac.uk (Graham Cox) Date: Mon, 7 Mar 1994 11:32:44 GMT Organization: School of Information Systems, UEA, Norwich In article <2lf1jh$rk2@news.kth.se>, d88-jwa@mumrik.nada.kth.se (Jon Wtte) wrote: > In <2lepqt$1g3@nic.lth.se> dat91jre@ludat.lth.se (Regmyr Jonas) writes: > > >Is there a way to tell one Mac from anotherone or, is there a way > >for a program to tell if it has been moved from one machine to > >anotherone, possible the same type (from, say, one Classic to another)? Here's a simple way. Get the Date/Time of initialization of the startup disk. As this is accurate to the second, the chance of two Macs having their hard disks initialised at the same time is very small. You can store this value in your app's preferences, and compare it with the current disk at startup. If different, you can ask the user to enter a validation code. If correct, you can then update the disk "ID" so the user doesn't get bothered again, unless the program is copied to another machine. If you add some kind of encryption to the stored values, the likelihood of someone being able to hack the values is virtually non-existent. I used this method on a commercial app and it works a treat. It's also one of the few copy-protection methods thats absolutely compatible with the system and unlikely to fail in future releases. - ------------------------------------------------------------------------ Love & BSWK, Graham -Everyone is entitled to their opinion, no matter how wrong they may be... - ------------------------------------------------------------------------ +++++++++++++++++++++++++++ >From ajr3@quads.uchicago.edu (Alain Roy) Date: Mon, 7 Mar 1994 15:00:36 GMT Organization: University of Chicago In article u9119523@sys.uea.ac.uk (Graham Cox) writes: > >Here's a simple way. Get the Date/Time of initialization of the startup >disk. As this is accurate to the second, the chance of two Macs having >their hard disks initialised at the same time is very small. works unless you're like me: i have 2 hard drives. if every time i switched, i had the copy protection of a program fire up, i'd be really upset. -alain +++++++++++++++++++++++++++ >From time@garnet.msen.com (Tim Endres) Date: 7 Mar 1994 19:22:52 GMT Organization: Msen, Inc. -- Ann Arbor, MI (account info: +1 313 998-4562) Matt Slot (fprefect@engin.umich.edu) wrote: : Regmyr Jonas, dat91jre@ludat.lth.se writes: : : >Is there a way to tell one Mac from another one or, is there a way : >for a program to tell if it has been moved from one machine to : >anotherone, possible the same type (from, say, one Classic to another)? : >If so, how do I do this? : ------------- : First a note: dont make self-modifying apps! Your app should not store : machine specific information within itself; if you save a preference : do it to a preferences file. Unless you need a self-modifying app, such as TransIt. : OK, off the podium. If you still need to identify a Mac from another, : use the Volume Creation date for VRefNum = -1. This is the long date : to the second of the initialization of that HD. For a 1 in 4 billion Except that most times are in the range from 1984 to 1994, as opposed to 1904 to 1994. Thus, closer to 478 Million. Still reasonable. : chance of duplication, this works rather well. If the user *does* : reformat the boot disk, it will probably be a full reinstall and for : all intents a "new" machine. Or, as pointed out, the user boots from more than one volume. In this case, you need to keep a "list" of drives, which may not be what you want. +++++++++++++++++++++++++++ >From gregor@nrlfs1.nrl.navy.mil (joe gregor) Date: Mon, 7 Mar 1994 19:45:14 GMT Organization: NRL In Article <2lf445$5qd@lastactionhero.rs.itd.umich.edu>, Matt Slot wrote: >OK, off the podium. If you still need to identify a Mac from another, >use the Volume Creation date for VRefNum = -1. This is the long date >to the second of the initialization of that HD. For a 1 in 4 billion >chance of duplication, this works rather well. If the user *does* >reformat the boot disk, it will probably be a full reinstall and for >all intents a "new" machine. > Never had to replace a hard disk before, huh. -- Joe +++++++++++++++++++++++++++ >From peirce@outpost.SF-Bay.org (Michael Peirce) Date: Mon, 7 Mar 94 13:52:36 PST Organization: Peirce Software, Inc. In article (comp.sys.mac.programmer), u9119523@sys.uea.ac.uk (Graham Cox) writes: > Here's a simple way. Get the Date/Time of initialization of the startup > disk. As this is accurate to the second, the chance of two Macs having > their hard disks initialised at the same time is very small. > > You can store this value in your app's preferences, and compare it with the > current disk at startup. If different, you can ask the user to enter a > validation code. If correct, you can then update the disk "ID" so the user > doesn't get bothered again, unless the program is copied to another > machine. If you add some kind of encryption to the stored values, the > likelihood of someone being able to hack the values is virtually > non-existent. I used this method on a commercial app and it works a treat. > It's also one of the few copy-protection methods thats absolutely > compatible with the system and unlikely to fail in future releases. How do people feel about this technique. Are there any obvious drawbacks? It does mean you need to "install" the software on each new system disk, any objections to this? -- Michael Peirce -- peirce@outpost.sf-bay.org -- Peirce Software, Inc. -- 719 Hibiscus Place, Suite 301 -- -- San Jose, California USA 95117 -- Makers of: Smoothie & -- voice: +1.408.244.6554 fax: +1.408.244.6882 -- Peirce Print Tools -- AppleLink: peirce & America Online: AFC Peirce +++++++++++++++++++++++++++ >From peter@ncrpda.curtin.edu.au (Peter N Lewis) Date: 8 Mar 1994 13:04:08 +0800 Organization: NCRPDA, Curtin University time@garnet.msen.com (Tim Endres) writes: >: First a note: dont make self-modifying apps! Your app should not store >: machine specific information within itself; if you save a preference >: do it to a preferences file. >Unless you need a self-modifying app, such as TransIt. Besides, it's perfectly reasonable to modify yourself during instalation. But it would definiitely be bad later on when the admin has writeprotected the directory (and it's not much use on CDROMs either, etc). >Or, as pointed out, the user boots from more than one >volume. In this case, you need to keep a "list" of >drives, which may not be what you want. That's not really needed - if you boot from a seperate disk, then you'll have a seperate prefs file, so you'll have to enter the serial number once per system folder, thats not particularly unreasonable (and I hate copy protection!). The main draw back of this scheme is that it's a royal pain in the ass for network mutli-user licenses. I think you can guess how happy I'd be to buy a twenty user license and then have the fun of going around typing serial numbers into every damn machine - and since this is such a pain, I'll probably not recomend your software as the one to buy... Peter. -- Peter N Lewis Ph: +61 9 368 2055 +++++++++++++++++++++++++++ >From ivanski@world.std.com (Ivan M CaveroBelaunde) Date: Tue, 8 Mar 1994 16:30:43 GMT Organization: The World Public Access UNIX, Brookline, MA peirce@outpost.SF-Bay.org (Michael Peirce) writes: >In article (comp.sys.mac.programmer), u9119523@sys.uea.ac.uk (Graham Cox) writes: >> Here's a simple way. Get the Date/Time of initialization of the startup >> disk. As this is accurate to the second, the chance of two Macs having >> their hard disks initialised at the same time is very small. >> >> You can store this value in your app's preferences, and compare it with the >> current disk at startup. If different, you can ask the user to enter a >> validation code. If correct, you can then update the disk "ID" so the user >> doesn't get bothered again, unless the program is copied to another >> machine. If you add some kind of encryption to the stored values, the >> likelihood of someone being able to hack the values is virtually >> non-existent. I used this method on a commercial app and it works a treat. >> It's also one of the few copy-protection methods thats absolutely >> compatible with the system and unlikely to fail in future releases. >How do people feel about this technique. Are there any obvious drawbacks? >It does mean you need to "install" the software on each new system >disk, any objections to this? Actually, I really dislike the idea of having to install the software on each new system, or being unable to switch to a different startup disk (if say my startup volume died suddenly). I'd advocate a much different route (which might be in use right now, since I've seen software behave this way). Currently, a lot of software requires the user to do the first launch on a writable volume in order to store registration information. As long as it runs off of a read-only volume (ie a server) after that one registration step, that doesn't bother me, and I don't think most users would be hassled by this too much either. Consequently, I'd consider doing the following - when prompting the user for registration information (which would be stored inside the app), also look at the date/time of initialization of the volume CONTAINING THE APP, and also look at the fileID of the app itself (ie manually build a mini alias). Then store this information with the registration information inside the app, and check against it at app launch. This way, you can detect if the app file itself has been copied, and reprompt for registration info if this is the case. The method is flexible enough that if you wanted to allow some variants of copying (ie doing a duplicate on the app file in the finder), you could check that the app the reg info specifies is present and meets some basic checks (as opposed to requiring that the app you are RUNNING is the app the reg info points to). The other drawback is that this requires installation of software on read-only servers by users with write permission - but this requirement is present currently anyway. Comments? -Ivan - - Ivan Cavero Belaunde (ivanski@world.std.com) Avid VideoShop Project Lead Avid Technology, Inc. +++++++++++++++++++++++++++ >From peirce@outpost.SF-Bay.org (Michael Peirce) Date: Tue, 8 Mar 94 09:16:22 PST Organization: Peirce Software, Inc. In article <1994Mar7.150036.11171@midway.uchicago.edu> (comp.sys.mac.programmer), ajr3@quads.uchicago.edu (Alain Roy) writes: > In article u9119523@sys.uea.ac.uk (Graham Cox) writes: > > > >Here's a simple way. Get the Date/Time of initialization of the startup > >disk. As this is accurate to the second, the chance of two Macs having > >their hard disks initialised at the same time is very small. > > works unless you're like me: i have 2 hard drives. if every time i switched, > i had the copy protection of a program fire up, i'd be really upset. But this would only happen the first time you started up on your second disk. After that, its prefs file would contain the init time of *that* disk. -- Michael Peirce -- peirce@outpost.sf-bay.org -- Peirce Software, Inc. -- 719 Hibiscus Place, Suite 301 -- -- San Jose, California USA 95117 -- Makers of: Smoothie & -- voice: +1.408.244.6554 fax: +1.408.244.6882 -- Peirce Print Tools -- AppleLink: peirce & America Online: AFC Peirce +++++++++++++++++++++++++++ >From time@garnet.msen.com (Tim Endres) Date: 8 Mar 1994 18:47:42 GMT Organization: Msen, Inc. -- Ann Arbor, MI (account info: +1 313 998-4562) I really like Ivan's idea of storing the time for the disk that the *app* is on. This solves Peter's network installation problems and it solves CD and server setups. +++++++++++++++++++++++++++ >From mahboud@aggroup.com (Mahboud Zabetian) Date: Tue, 08 Mar 1994 11:37:13 -0800 Organization: AG Group, Inc. For macs with built-in Ethernet; Ethernet addresses are unique. -mahboud - ------------------------------------------------------------- Mahboud Zabetian mahboud@aggroup.com ag group, inc. 2540 camino diablo, suite 200 walnut creek, ca 94596 510-937-7900 voice 510-937-2479 fax 510-937-6704 ara ftp.aggroup.com anonymous ftp +++++++++++++++++++++++++++ >From Carl R. Osterwald Date: Tue, 8 Mar 94 20:41:45 GMT Organization: National Renewable Energy Laboratory In article Mahboud Zabetian, mahboud@aggroup.com writes: >For macs with built-in Ethernet; Ethernet addresses are unique. True, but what about machines that use Ethernet cards? If the card is changed for some reason, the nice app you spent good cash for no longer runs. +++++++++++++++++++++++++++ >From d88-jwa@mumrik.nada.kth.se (Jon Wätte) Date: 8 Mar 1994 21:16:28 GMT Organization: Royal Institute of Technology, Stockholm, Sweden In peirce@outpost.SF-Bay.org (Michael Peirce) writes: >It does mean you need to "install" the software on each new system >disk, any objections to this? Not popular among large sites. There is a way that an application can sense it's KeyServer keyed and turn off its internal copy protection, though. -- -- Jon W{tte, h+@nada.kth.se, Mac Hacker Deluxe -- I should have stayed at the bus station. +++++++++++++++++++++++++++ >From DACRXL01.OURX124@tcp30.dx.deere.com (Juan Ingles) Date: Wed, 9 Mar 1994 00:37:18 GMT Organization: Proteus Ventures, Inc. In article Carl R. Osterwald writes: > In article Mahboud Zabetian, > mahboud@aggroup.com writes: > >For macs with built-in Ethernet; Ethernet addresses are unique. > > True, but what about machines that use Ethernet cards? If the card is > changed for some reason, the nice app you spent good cash for no longer > runs. The ethernet address would still be the same. The address is assigned to the machine and not to the card. The address is kept by the Mac TCP software. (and can ussually be typed in by the user) Addresses can and do change for other reasons, though. Administrators can reassign addresses, the ethernet class could change, the machine could be moved to a different network, etc. Juan Ingles -- Proteus Ventures, Inc. - Computer Software Consulting and Development 1514 Oriole Ave * Waterloo, IA 50701 * (319) 232-0985 +++++++++++++++++++++++++++ >From peter@ncrpda.curtin.edu.au (Peter N Lewis) Date: 9 Mar 1994 11:48:59 +0800 Organization: NCRPDA, Curtin University ivanski@world.std.com (Ivan M CaveroBelaunde) writes: >Actually, I really dislike the idea of having to install the software on >each new system, or being unable to switch to a different startup disk >(if say my startup volume died suddenly). I'd advocate a much different route >(which might be in use right now, since I've seen software behave this >way). Currently, a lot of software requires the user to do the first launch >on a writable volume in order to store registration information. As long The problem with both these solutions is they are a pain to setup in a network environment, and since multiple copy licenses make up a large chunk of the revenue, it really doesn't do to piss of these people with anoying copy protection pains. I don't mind software that asks you to register it with a serial number and your name when you first install it, but if I have to do that for all twenty copies that I bought, I wont buy them in the first place. Piracy loses sales, but so does copy protection. Peter. -- Peter N Lewis Ph: +61 9 368 2055 +++++++++++++++++++++++++++ >From ari@world.std.com (Ari I Halberstadt) Date: Wed, 9 Mar 1994 07:31:34 GMT Organization: The World Public Access UNIX, Brookline, MA In article <2lf445$5qd@lastactionhero.rs.itd.umich.edu>, Matt Slot wrote: >OK, off the podium. If you still need to identify a Mac from another, >use the Volume Creation date for VRefNum = -1. This is the long date >to the second of the initialization of that HD. For a 1 in 4 billion >chance of duplication, this works rather well. If the user *does* >reformat the boot disk, it will probably be a full reinstall and for >all intents a "new" machine. We can assume that all Macintosh hard drives have been formatted no earlier than 1983 and no later than 1994 (assuming the user remembered to set the clock before formatting). This gives a range of about 3.47x10^8 seconds, or 347 million. Most drives have probably been formatted in only the last 4 years (there weren't even hard drives for the mac until '85, I think), so it's probably more like 1.26x10^8 seconds. This is still a big number, but it's not nearly in the billions. -- Ari Halberstadt ari@world.std.com #include "These beetles were long considered to be very rare because very few entomologists look for beetles in the mountains, in winter, at night, during snow storms." -- Purves W. K., et al, "Life: The Science of +++++++++++++++++++++++++++ >From dwalton1@bach.helios.nd.edu (david walton) Date: 9 Mar 1994 08:21:54 GMT Organization: University of Notre Dame, Notre Dame In article DACRXL01.OURX124@tcp30.dx.deere.com (Juan Ingles) writes: >In article >Carl R. Osterwald writes: > >> In article Mahboud Zabetian, >> mahboud@aggroup.com writes: >> >For macs with built-in Ethernet; Ethernet addresses are unique. >> >> True, but what about machines that use Ethernet cards? If the card is >> changed for some reason, the nice app you spent good cash for no longer >> runs. > >The ethernet address would still be the same. The address is assigned >to the machine and not to the card. The address is kept by the Mac TCP >software. (and can ussually be typed in by the user) *Ethernet* addresses are assigned to the physical hardware on the card (which card may be moved around from machine to machine). *IP addresses* (which I think is what you mean) are configurable by the MacTCP Control Panel and can therefore be changed by any user (although AdminTCP may be required if the network administrator was smart enough to lock the settings). If some form of BOOTP is used, then the administrator controls which interface gets which address, but the user can always configure MacTCP to use a static address. (Which address, btw, often ends up being one which was assigned to another user--anyone who's dealt with the "this IP address is already in use" message from MacTCP when some putz on your local network steals an address will know exactly what I'm talking about). Point is, you can't assume a fixed relationship between either ethernet or IP addresses and a particular machine, except in the limiting case where the ethernet hardware's built in. Hence, this would not be a reliable copy-protection scheme in the general case. Not that I _want_ copy-protection, mind you.... Now that I think about it, it's not trivial to get the Ethernet address on built-in hardware if the machine doesn't have a transceiver with an active link attached. (Is is possible to do this, BTW? I don't see any way of doing it by making MacTCP calls, but is there a lower-level driver call that could return this information?) David -- { David Walton School: Dept. of History and Philosophy of Science } { Work: Office of University Computing } { Mail: David.Walton.10@nd.edu } { Any unquoted opinions expressed herein are...well...mine. Pity. } +++++++++++++++++++++++++++ >From d88-jwa@mumrik.nada.kth.se (Jon Wätte) Date: 9 Mar 1994 15:07:28 GMT Organization: Royal Institute of Technology, Stockholm, Sweden In DACRXL01.OURX124@tcp30.dx.deere.com (Juan Ingles) writes: >> True, but what about machines that use Ethernet cards? If the card is >> changed for some reason, the nice app you spent good cash for no longer >> runs. >The ethernet address would still be the same. The address is assigned >to the machine and not to the card. The address is kept by the Mac TCP >software. (and can ussually be typed in by the user) PLEASE get your facts straigt at least. Ethernet addresses are hardcoded in the Ethernet card ROM, and no two cards EVER have the same address. The IP address is what's maintained by MacTCP. Totally different beast. Even if you don't install MacTCP, the ethernet address is there in the ethernet card (even if you turn off AppleTalk!) Ethernet breaks. Motherboard break. Users upgrade software. If you've GOT to have copy protection, and don't mind breaking on PowerBook Duos, use an ADB dongle; safe & efficient, upgradable, and the money you save by not being pirated should pay for the dongle price; if you subscribe to that theory. (I do for some special niche products I make) -- -- Jon W{tte, h+@nada.kth.se, Mac Hacker Deluxe -- What we need is a good GNU [...] licence manager implementation. -- Raphael Manfredi +++++++++++++++++++++++++++ >From DACRXL01.OURX124@tcp30.dx.deere.com (Juan Ingles) Date: Wed, 9 Mar 1994 16:49:05 GMT Organization: Proteus Ventures, Inc. In article <2lk0v2$oq3@news.nd.edu> dwalton1@bach.helios.nd.edu (david walton) writes: > *Ethernet* addresses are assigned to the physical hardware on the card > (which card may be moved around from machine to machine). *IP > addresses* (which I think is what you mean) Yea, I meant IP. I'm not a hardware person, so I had never heard of Ethernet adresses on the cards and assumed that the "adress" mentioned was an IP address. Juan Ingles -- Proteus Ventures, Inc. - Computer Software Consulting and Development 1514 Oriole Ave * Waterloo, IA 50701 * (319) 232-0985 +++++++++++++++++++++++++++ >From Paul Ferguson Date: 9 Mar 1994 19:06:06 GMT Organization: Kaleida Labs, Inc. In article <2lk0v2$oq3@news.nd.edu> david walton, dwalton1@bach.helios.nd.edu writes: > Now that I think about it, it's not trivial to get the Ethernet > address on built-in hardware if the machine doesn't have a transceiver > with an active link attached. (Is is possible to do this, BTW? I > don't see any way of doing it by making MacTCP calls, but is there a > lower-level driver call that could return this information?) Yes, there is a device driver call to the EtherTalk driver to return the Ethernet address. All Ethernet cards have their Ethernet address PROM memory mapped into the physical address space, but there is no standard for where this may be. Therefore, directly accessing the Ethernet address is highly vendor dependent. Also, there is a defined method for providing a "soft" Ethernet address in a resource that will override the hardware Ethernet address. --fergy - ------------------------------------------------------------------ Paul Ferguson | "It's a sick world, I'm a happy guy..." pferguson@kaleida.com | - ------------------------------------------------------------------ +++++++++++++++++++++++++++ >From DACRXL01.OURX124@tcp30.dx.deere.com (Juan Ingles) Date: Wed, 9 Mar 1994 23:05:51 GMT Organization: Proteus Ventures, Inc. In article <2lkong$k0c@news.kth.se> d88-jwa@mumrik.nada.kth.se (Jon Wätte) writes: > >The ethernet address would still be the same. The address is assigned > >to the machine and not to the card. The address is kept by the Mac TCP > >software. (and can ussually be typed in by the user) > > PLEASE get your facts straigt at least. Hey! My facts were straight! I was just talking about something completly different than everyone else was! That's all! :) (Is that the Topic Police I hear coming?.....) Juan Ingles -- Proteus Ventures, Inc. - Computer Software Consulting and Development 1514 Oriole Ave * Waterloo, IA 50701 * (319) 232-0985 -- Yes, I understand that you understood what I said. What you don't understand is that I didn't say what I meant. +++++++++++++++++++++++++++ >From peterb@tcc.oecn.ohio.gov (Peter Bierman) Date: Sun, 13 Mar 1994 22:32:50 GMT Organization: Linworth Alternative HS In article <2lih8e$l5b@nigel.msen.com>, time@garnet.msen.com (Tim Endres) wrote: > I really like Ivan's idea of storing the time for the disk > that the *app* is on. This solves Peter's network installation > problems and it solves CD and server setups. But what if the user transfers the app to a different volume because of low disk space? I do this all the time. -- Peter Bierman \ The Metropolis \ The most primitive part of the peterb@tcc.oecn.ohio.gov \ (614)-846-1911 \ the brain concerns itself \ 600MB Mac Files \ with the "Four F's": "I've changed my mind, Hobbes \ FirstClass \ Feeding, Fighting, Fleeing, people are scum." --Calvin \ Mac & Windows \ and Reproduction. +++++++++++++++++++++++++++ >From noah@apple.com (Noah Price) Date: Thu, 10 Mar 1994 23:49:02 GMT Organization: (not the opinions of) Apple Computer, Inc. In article , peirce@outpost.SF-Bay.org (Michael Peirce) wrote: > In article <1994Mar7.150036.11171@midway.uchicago.edu>, ajr3@quads.uchicago.edu (Alain Roy) writes: > > > > works unless you're like me: i have 2 hard drives. if every time i switched, > > i had the copy protection of a program fire up, i'd be really upset. > > But this would only happen the first time you started up on your second > disk. After that, its prefs file would contain the init time of *that* > disk. But what if he switches back and forth between the two disks often for whatever reason? noah ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Noah Price (not the opinions of) Apple Computer, Inc. Macintosh AV Hardware 20525 Mariani Ave., MS 60-TNT noah@apple.com Cupertino CA 95014 +++++++++++++++++++++++++++ >From zdelesde@vt.edu (Zac DeLesDernier) Date: 18 Mar 1994 03:17:41 GMT Organization: Virginia Tech I have a related question. I need a way to uniquely identify a file, other than its name. This identifying mechanism should also work for copies of a file. (i.e. A backup would have the same file id.) The id should _not_ change if the file is renamed or moved. (I hope I am making myself clear.) One idea I had was writing some bignum into the VERS resource, but then I dont want this marking system to mangle applications (or anything else that might have a valid VERS resource.) Any ideas? - - Zac DeLesDernier zdelesde@vt.edu --------------------------- >From bdiamand@netcom.com (Ben Diamand) Subject: I know the Mac MM isn't reentrant, but: Date: Thu, 10 Mar 1994 03:12:17 GMT Organization: NETCOM On-line Communication Services (408 241-9760 guest) I know the Mac MM isn't reentrant, but, can I call HUnlock from within an interrupt(read:completion routine/callBack)? If the answer is no, would some mac guru care to post/email a way to let the Mac Memory Manager know that a handle no longer needs to locked? I realize it's been a long time since the high byte was used for this purpose, but the same info's got to be somewhere, right?! As a further question to the same person who tells me how to change this(assuming anyone does :) ), am I doomed in native/emulated PowerPC using whatever means you give me to change this attribute? Thanks! Ben Diamand bdiamand@netcom.com ALINK:bdiamand +++++++++++++++++++++++++++ >From resnick@cogsci.uiuc.edu (Pete Resnick) Date: Wed, 09 Mar 1994 23:07:59 -0600 Organization: University of Illinois at Urbana-Champaign In article , bdiamand@netcom.com (Ben Diamand) wrote: >I know the Mac MM isn't reentrant, but, can I call HUnlock from within an >interrupt(read:completion routine/callBack)? HUnlock is not on the list of routines that cannot be called at interrupt time. It should be safe. pr -- Pete Resnick (...so what is a mojo, and why would one be rising?) Graduate assistant - Philosophy Department, Gregory Hall, UIUC System manager - Cognitive Science Group, Beckman Institute, UIUC Internet: resnick@cogsci.uiuc.edu +++++++++++++++++++++++++++ >From bdiamand@netcom.com (Ben Diamand) Date: Thu, 10 Mar 1994 07:25:56 GMT Organization: NETCOM On-line Communication Services (408 241-9760 guest) Pete Resnick (resnick@cogsci.uiuc.edu) wrote: : In article , bdiamand@netcom.com (Ben : Diamand) wrote: : >I know the Mac MM isn't reentrant, but, can I call HUnlock from within an : >interrupt(read:completion routine/callBack)? : HUnlock is not on the list of routines that cannot be called at interrupt : time. It should be safe. Thank-you for the reply...Ya, I know that it's not on the list. But, I have great fear regarding interrupts and the MM, Sound Manager, and the File Manager. They all use interrupts to get their respective jobs done and they all are incorrectly documented with respect to interrupts in various versions of IM. Sound Manager 3.0 seems to fix many problems that I had with sound interrupts, but I stiil am very leary(sp?) of the Mac MM. Maybe I'm a Unix person at heart? :) Ben Diamand bdiamand@netcom.com ALINK:bdiamand +++++++++++++++++++++++++++ >From gurgle@netcom.com (Pete Gontier) Date: Thu, 10 Mar 1994 17:52:59 GMT Organization: cellular resnick@cogsci.uiuc.edu (Pete Resnick) writes: >In article , bdiamand@netcom.com (Ben >Diamand) wrote: >>I know the Mac MM isn't reentrant, but, can I call HUnlock from within an >>interrupt(read:completion routine/callBack)? >HUnlock is not on the list of routines that cannot be called at interrupt >time. It should be safe. Apple has now disowned that list. Apple says that although there are traps which can be called at interrupt time, the list is out of date. In particular, I can imagine HUnlock being one of the traps that would fail or misbehave at interrupt time. If the handle's flags were kept in a prefix to the buffer rather than in the master pointer list, the Memory Manager could be in the middle of shuffling that block when HUnlock occurred, and the master pointer might not be updated yet. I'm not sure, but I think this may be possible in a 32-bit heap. In any case, it's not something I would want to rely on. Apple is changing the implementation of the Memory Manager under System 7 for PowerPC, which means there will be at least 3 known major versions of the MM. Since the MM is one of the most sensitive areas with regard to interrupt time, I wouldn't push my luck. But now I'm curious -- why would you want to unlock a handle at interrupt time? -- Pete Gontier, CTO, Integer Poet Software; gurgle@netcom.com +++++++++++++++++++++++++++ >From ivanski@world.std.com (Ivan M CaveroBelaunde) Date: Thu, 10 Mar 1994 15:28:20 GMT Organization: The World Public Access UNIX, Brookline, MA resnick@cogsci.uiuc.edu (Pete Resnick) writes: >In article , bdiamand@netcom.com (Ben >Diamand) wrote: >>I know the Mac MM isn't reentrant, but, can I call HUnlock from within an >>interrupt(read:completion routine/callBack)? >HUnlock is not on the list of routines that cannot be called at interrupt >time. It should be safe. Actually, the list is described as "routines that move memory." I don't believe this implies that all other routines can be called at interrupt time - certainly reentrancy can be an issue even for routines that do not move memory. I'd be a little queasy about unlocking a handle from interrupt time, for a couple of reasons: o In the best of cases, that handle must be locked. It's perfectly legal to unlock an unlocked handle, but if done at interrupt time you would hose yourself badly. I'd do an HGetState before that - of course, I'm not sure whether it's safe to call HGetState on an unlocked block during interrupt time in the first place, so unless it's always locked or you keep parallel state somewhere alse (ie global storage) this becomes a catch-22. o Non-reentrancy of the memory manager. I believe the memory manager uses private pieces of low memory for temporary storage, which might get nuked if you call HUnlock in the middle of another mem mgr operation. Also, while I don't know whether the "old" memory manager checks handle validity on an HUnlock operation (by walking the free master pointer lists, a no-no at interrupt time), the "new" memory manager that has appeared on developer CDs in prerelease version can be placed into a mode that performs that check. o Patches. There are probably more than a few INITs/extensions out there that patch HUnlock and do their own thing. While it is completely illegal for them to move memory in their patch, whether they could assume that the heaps are in a consistent state (an invalid assumption at interrupt time) is a gray area. Coupled with the fact that if your app is incompatible with a popular extension, it will be your app that is blamed, not that extension (unless the extension is known as a particularly troublesome one), this'd make me very wary. For what it's worth, I wouldn't do it. I'd set a global flag and do it from interrupt safe-land (like the event loop). -Ivan - - Ivan Cavero Belaunde (ivanski@world.std.com) Avid VideoShop Project Lead Avid Technology, Inc. +++++++++++++++++++++++++++ >From mgr@aggroup.aggroup.com (Mike Russell) Date: Thu, 10 Mar 1994 12:05:29 -0800 Organization: the ag group, inc. In article , bdiamand@netcom.com (Ben Diamand) wrote: > > I know the Mac MM isn't reentrant, but, can I call HUnlock from within an > interrupt(read:completion routine/callBack)? YOW - even if it's otherwise legal, consider the problems the following non-interrupt code could run into if myHandle is unlocked asynchronously: SignedByte s = HGetState(myHandle); HLock(myHandle); ... Do some stuff ... HSetState(myHandle, s); So be very careful about who else might be looking at the locked block. A safer way to do this - DTInstall(), IM V-467. +++++++++++++++++++++++++++ >From resnick@cogsci.uiuc.edu (Pete Resnick) Date: 11 Mar 1994 02:03:15 GMT Organization: University of Illinois at Urbana mgr@aggroup.aggroup.com (Mike Russell) writes: >So be very careful about who else might be looking at the locked block. >A safer way to do this - DTInstall(), IM V-467. No, DTInstall won't help. Deferred tasks get executed at a time which is effectively the same as interrupt time. It is no safer to call a routine at deferred task time than at interrupt time. pr -- Pete Resnick (...so what is a mojo, and why would one be rising?) Graduate assistant - Philosophy Department, Gregory Hall, UIUC System manager - Cognitive Science Group, Beckman Institute, UIUC Internet: resnick@cogsci.uiuc.edu +++++++++++++++++++++++++++ >From resnick@cogsci.uiuc.edu (Pete Resnick) Date: 11 Mar 1994 02:10:29 GMT Organization: University of Illinois at Urbana ivanski@world.std.com (Ivan M CaveroBelaunde) writes: >Actually, the list is described as "routines that move memory." No, the list at the end of the second edition of the X-Ref is "routines that can't be called at interrupt." Some of them move memory; some of them aren't reentrant. pr -- Pete Resnick (...so what is a mojo, and why would one be rising?) Graduate assistant - Philosophy Department, Gregory Hall, UIUC System manager - Cognitive Science Group, Beckman Institute, UIUC Internet: resnick@cogsci.uiuc.edu +++++++++++++++++++++++++++ >From quinn@cs.uwa.edu.au (Quinn "The Eskimo!") Date: Fri, 11 Mar 1994 12:14:37 +0800 Organization: Department of Computer Science, The University of Western Australia In article , resnick@cogsci.uiuc.edu (Pete Resnick) wrote: >In article , bdiamand@netcom.com (Ben >Diamand) wrote: > >>I know the Mac MM isn't reentrant, but, can I call HUnlock from within an >>interrupt(read:completion routine/callBack)? > >HUnlock is not on the list of routines that cannot be called at interrupt >time. It should be safe. I hate to be picky but this is ***RONG!!!!*** If you don't believe me read Kon & Bal's puzzle page in develop 16. Here's an extract.... - -------------------- Mike The interesting part of the heap before and after the MoveHHi call is shown in the figure. Before MoveHHi there was a locked block, labeled A in the figure, which is marked as relocatable afterward. The relocatable block just below locked block B is getting overwritten by the block we¹re calling MoveHHi on. KON MoveHHi works by first saving the contents of the block that you¹re moving, then marking the block as free. Then it calls CompactMem on the heap, which bubbles all the free space up to any islands and all relocatable blocks down. Then it copies the block to the free block just before the island. BAL And someone is coming in at interrupt time and unlocking the island, block A in the figure. Instead of remembering the location of the island, MoveHHi searches for it after the CompactMem call. Since that block was unlocked by an interrupt after CompactMem, a different block is found the second time. When MoveHHi backs up to the previous, presumably free, block and starts copying data, the heap gets trashed. Mike Yeah, that interrupt unlocking the block was QuickTime, BAL. It turns out the Sound Manager does the same thing. Apparently the ³system architects² at the time thought it was OK to call HUnlock on a locked block during an interrupt. Not! We fixed it by deferring all HUnlock calls until MoveHHi finishes. This was the cleanest fix; it keeps us from patching out huge parts of the Memory Manager. But we were stumped for quite a while. KON Nasty. BAL Yeah. - -------------------- I'm sorry about the formatting but I cut and pasted it out of the magazine on the CD. Please read the article for a better explanation. -- Quinn "The Eskimo!" "Support HAVOC!" Department of Computer Science, The University of Western Australia I hate newsreaders that complain about more quoted text than article text. My quotes weren't from another article. Grrrrr!!!!! +++++++++++++++++++++++++++ >From bdiamand@netcom.com (Ben Diamand) Date: Fri, 11 Mar 1994 07:41:42 GMT Organization: NETCOM On-line Communication Services (408 241-9760 guest) Mike Russell (mgr@aggroup.aggroup.com) wrote: : In article , bdiamand@netcom.com (Ben : Diamand) wrote: : > : > I know the Mac MM isn't reentrant, but, can I call HUnlock from within an : > interrupt(read:completion routine/callBack)? : YOW - even if it's otherwise legal, consider the problems the following : non-interrupt code could run into if myHandle is unlocked asynchronously: : SignedByte s = HGetState(myHandle); : HLock(myHandle); : ... Do some stuff ... : HSetState(myHandle, s); : So be very careful about who else might be looking at the locked block. : A safer way to do this - DTInstall(), IM V-467. My non-interrupt code locks the handle as soon as it gets it and then 'forgets' about the handle. The interrupt code handles the handles:) Ben Diamand bdiamand@netcom.com ALINK:bdiamand +++++++++++++++++++++++++++ >From bdiamand@netcom.com (Ben Diamand) Date: Fri, 11 Mar 1994 07:46:12 GMT Organization: NETCOM On-line Communication Services (408 241-9760 guest) Quinn "The Eskimo! (quinn@cs.uwa.edu.au) wrote: : In article , : resnick@cogsci.uiuc.edu (Pete Resnick) wrote: : >In article , bdiamand@netcom.com (Ben : >Diamand) wrote: : > : >>I know the Mac MM isn't reentrant, but, can I call HUnlock from within an : >>interrupt(read:completion routine/callBack)? : > : >HUnlock is not on the list of routines that cannot be called at interrupt : >time. It should be safe. : I hate to be picky but this is ***RONG!!!!*** : If you don't believe me read Kon & Bal's puzzle page in develop 16. : Here's an extract.... [text deleted] : ---------------------- : Mike Yeah, that interrupt unlocking the block was QuickTime, : BAL. It turns out the Sound Manager does the same thing. Apparently the : ³system architects² at the time thought it was OK to call HUnlock on a : locked block during an interrupt. Not! We fixed it by deferring all : HUnlock calls until MoveHHi finishes. This was the cleanest fix; it keeps : us from patching out huge parts of the Memory Manager. But we were stumped : for quite a while. : KON Nasty. : BAL Yeah. : ---------------------- : I'm sorry about the formatting but I cut and pasted it out of the : magazine on the CD. Please read the article for a better explanation. : -- : Quinn "The Eskimo!" "Support HAVOC!" : Department of Computer Science, The University of Western Australia : I hate newsreaders that complain about more quoted text than article : text. My quotes weren't from another article. Grrrrr!!!!! Ok, now here's a stupid question. How does one know when MoveHHi is done? I don't mind terribly defering the HUnlock...I just wanted to know if I had to...Thanks forthe reply... Ben Diamand bdiamand@netcom.com ALINK:bdiamand +++++++++++++++++++++++++++ >From Duane Murphy Date: Mon, 14 Mar 1994 16:14:32 GMT Organization: Novell, Inc. In article Ben Diamand, bdiamand@netcom.com writes: >I know the Mac MM isn't reentrant, but, can I call HUnlock from within an >interrupt(read:completion routine/callBack)? If the answer is no, would Ben, There is a great article in develop issue 16 in KON & BAL's Puzzle Page that talks about just this problem. I just read it last week. Even the guru's at Apple think that HUnlock can be called at interrupt time. The problem stems from the algorithm used for MoveHHI. I don't quite understand it enough to explain it, but if the handle gets unlocked at the wrong time then MoveHHI will overwrite the handle. Check out the article, it is pretty interesting (especially for debugging techniques). Later, ...Duane +------------------------+--------------------------------------------+ | Duane Murphy | My opinions are mine, mine, and only mine; | | damurphy@wc.novell.com | Except when they are also yours. | +------------------------+--------------------------------------------+ +++++++++++++++++++++++++++ >From Steve Ethier Date: Mon, 14 Mar 1994 18:03:43 GMT Organization: Novell, Inc. In article <1994Mar14.161432.18054@novell.com> Duane Murphy, damurphy@wc.novell.com writes: >In article Ben Diamand, >bdiamand@netcom.com writes: >>I know the Mac MM isn't reentrant, but, can I call HUnlock from within >an >>interrupt(read:completion routine/callBack)? If the answer is no, would >Ben, >There is a great article in develop issue 16 in KON & BAL's Puzzle Page >that talks about just this problem. I just read it last week. Even the >guru's at Apple think that HUnlock can be called at interrupt time. > >The problem stems from the algorithm used for MoveHHI. I don't >quite understand it enough to explain it, but if the handle gets unlocked >at the wrong time then MoveHHI will overwrite the handle. > >Check out the article, it is pretty interesting (especially for debugging >techniques). > >Later, >...Duane Ben, the "short form" to Duane's answer is that HUnlock is *not* safe to call at interrupt time. (Duane let me read the article, and I must admit that it is indeed very interesting.) Steve Ethier ethier@wc.novell.com +++++++++++++++++++++++++++ >From David A Lyons Date: Thu, 10 Mar 1994 22:26:21 GMT Organization: Apple Computer, Inc. In article Pete Gontier, gurgle@netcom.com writes: > In particular, I can imagine HUnlock being one of the traps that would > fail or misbehave at interrupt time. Correct, calling HUnlock at interrupt time is bad. See Kon and Bal's Puzzle Page in _develop_ #16 (December 1993). Dave Lyons, dlyons@apple.com Mr Tangent My opinions are my own, not Apple's. --------------------------- >From mahboud@aggroup.com (Mahboud Zabetian) Subject: If you use SysBeep() for debugging... Date: Wed, 23 Feb 1994 15:07:55 -0800 Organization: AG Group, Inc. If you're like me and like to throw in SysBeep() calls in questionable code to help determine program flow, be careful! SysBeep() may move memory and could potentially make dereferenced handles invalid! This is a hard one to chase down, since you now have another bug added to whatever bug you were originally looking for. Hope this helps someone. -mahboud - ------------------------------------------------------------- Mahboud Zabetian mahboud@aggroup.com ag group, inc. 2540 camino diablo, suite 200 walnut creek, ca 94596 510-937-7900 voice 510-937-2479 fax 510-937-6704 ara ftp.aggroup.com anonymous ftp +++++++++++++++++++++++++++ >From blume@twg.com (David Blume) Date: Wed, 23 Feb 1994 23:56:35 GMT Organization: Gokuraku Videos - Wollongong Dept. mahboud@aggroup.com (Mahboud Zabetian) wrote: >If you're like me and like to throw in SysBeep() calls in questionable code >to help determine program flow, be careful! > >SysBeep() may move memory and could potentially make dereferenced handles >invalid! According to IM2, SysBeep() is stack-based. Also, my handy-dandy Online reference doesn't have the diamond character indicating that it moves memory. However, 411 does agree with Mahboud. It says that SysBeep() does move or purge memory. Sneaky... --David +-------------------------------------------------------------------------+ | David Blume | "A, Ayukawa!" | "Moemichan! ... SUKIDA!!" -- Youta | | blume@twg.com | "Kasuga-kuun..." | "Suckerfish!" -- Ai Amano | +-------------------------------------------------------------------------+ +++++++++++++++++++++++++++ >From danprice@delphi.com Date: Wed, 23 Feb 94 19:51:33 -0500 Organization: Delphi (info@delphi.com email, 800-695-4005 voice) Wow, good point. Any suggestions for an easy debugging tool like sysbeep()? Has anyone had a problem w/ sysbeep() doing this? -dp +++++++++++++++++++++++++++ >From mahboud@aggroup.com (Mahboud Zabetian) Date: Wed, 23 Feb 1994 22:51:49 -0800 Organization: AG Group, Inc. In article <1994Feb23.235635.17269@twg.com>, blume@twg.com (David Blume) wrote: > mahboud@aggroup.com (Mahboud Zabetian) wrote: > >If you're like me and like to throw in SysBeep() calls in questionable code > >to help determine program flow, be careful! > > > >SysBeep() may move memory and could potentially make dereferenced handles > >invalid! > > According to IM2, SysBeep() is stack-based. Also, my handy-dandy Online > reference doesn't have the diamond character indicating that it moves > memory. > Back in the days of the 128K and 512K mac, SysBeep() just played a good ole beep. A tone. Now that it plays digitized sounds, it seems to do a GetResource and/or LoadResource to get the sound. You can verify with an A-Trap break (Don't ATB on GetResource; Do an ATb for SysBeep, then when you are in the debugger, setup an ATB GetResource. You'll see 'snd ' on the stack). > However, 411 does agree with Mahboud. It says that SysBeep() does move > or purge memory. Sneaky... > > --David > +-------------------------------------------------------------------------+ > | David Blume | "A, Ayukawa!" | "Moemichan! ... SUKIDA!!" -- Youta | > | blume@twg.com | "Kasuga-kuun..." | "Suckerfish!" -- Ai Amano | > +-------------------------------------------------------------------------+ Sneaky is right. I was been bitten by this one 3 years ago too. Hard to figure out. -mahboud - ------------------------------------------------------------- Mahboud Zabetian mahboud@aggroup.com ag group, inc. 2540 camino diablo, suite 200 walnut creek, ca 94596 510-937-7900 voice 510-937-2479 fax 510-937-6704 ara ftp.aggroup.com anonymous ftp +++++++++++++++++++++++++++ >From mahboud@aggroup.com (Mahboud Zabetian) Date: Wed, 23 Feb 1994 22:58:58 -0800 Organization: AG Group, Inc. In article , danprice@delphi.com wrote: > > Wow, good point. Any suggestions for an easy debugging tool like sysbeep()? > > Has anyone had a problem w/ sysbeep() doing this? > > -dp Here's one way that I am trying out, but it's not audible like SysBeep(). I start at one end of my window and turn a pixel on. Using SetCPixel, I can setup the color too. I was mainly interested in doing this from an interrupt handler (I never checked to see if it moved memory, sorry), and it seemed to work fine, except that it was slow compared to my interrupt handler, and was slowing everything down. Are there still LowMem globals reserved for apps to use? If so, maybe the application under test could write a status value into that global, and can be checked at a later time? Any other thoughts appreciated... -mahboud - ------------------------------------------------------------- Mahboud Zabetian mahboud@aggroup.com ag group, inc. 2540 camino diablo, suite 200 walnut creek, ca 94596 510-937-7900 voice 510-937-2479 fax 510-937-6704 ara ftp.aggroup.com anonymous ftp +++++++++++++++++++++++++++ >From pottier@corvette.ens.fr (Francois Pottier) Date: 24 Feb 1994 10:39:07 GMT Organization: Ecole Normale Superieure, PARIS, France In article , Mahboud Zabetian wrote: >> Wow, good point. Any suggestions for an easy debugging tool like sysbeep()? Why not use the DebugStr call ? For instance, if I'm not mistaken, DebugStr('Checkpoint 1 ; g'); should print "Checkpoint 1" into Macsbug and resume execution. -- Francois Pottier ___ ___ _ _ / ___ ___ ___ pottier@dmi.ens.fr /_ /__/ /_| /| / / / / / / /__ / / \ / | / |/ /___ /__/ / ___/ _ / +++++++++++++++++++++++++++ >From tzs@u.washington.edu (Tim Smith) Date: 24 Feb 1994 10:43:04 GMT Organization: University of Washington School of Law, Class of '95 In article , wrote: >Wow, good point. Any suggestions for an easy debugging tool like sysbeep()? One thing I found real useful for debugging was to write my own printf that wrote directly to screen memory. It used a simple built in font (with each character being 3x5--yes, you can actually make a legible character set with 3x5--so that the memory manipulation would be easy). With this, I could get debugging information from all kinds of places where regular debug tools might fail: ethernet interrupt routines, SCSI boot code, Nubus card interrupts, etc., and I didn't have to worry about memory being moved, or managers not being in the proper state, or whatever. Unfortunately, I wrote this as part of my job, so I can't post it. --Tim Smith +++++++++++++++++++++++++++ >From kledbetter@aol.com (KLedbetter) Date: 24 Feb 1994 13:34:01 -0500 Organization: America Online, Inc. >>Wow, good point. Any suggestions for an easy debugging tool like >> sysbeep()? Well, if you're using C and System 7, you might want to look for my program "DebugWindow 2.0". It uses AppleEvents to easily display messages in a debugging window. Simply add DebugWindow.Lib to your project, and then you can do things like: Debug ("Just starting so-and-so routine\r"); ..... Debug ("Value of index is now %d\r", index); Keith +++++++++++++++++++++++++++ >From perlis_a@math.lsu.edu (Alexander Perlis) Date: 25 Feb 1994 00:47:14 GMT Organization: Louisiana State University InterNetNews Site In article <1994Feb23.235635.17269@twg.com> blume@twg.com (David Blume) writes: > mahboud@aggroup.com (Mahboud Zabetian) wrote: > >If you're like me and like to throw in SysBeep() calls in questionable code > >to help determine program flow, be careful! > > > >SysBeep() may move memory and could potentially make dereferenced handles > >invalid! > > According to IM2, SysBeep() is stack-based. Also, my handy-dandy Online > reference doesn't have the diamond character indicating that it moves > memory. > > However, 411 does agree with Mahboud. It says that SysBeep() does move > or purge memory. Sneaky... > > --David I would presume that this inconsistency in the documentation has to do with changes to the SysBeep() trap after the Sound Manager was added to the system software a few years back. At that point, SysBeep() no longer accessed the speaker or low-level sound routines directly, but instead called the Sound Manager to play the current system beep sound. The Sound Manager, being complicated and supporting different sounds stored in various formats in resources, obviously moves memory to do its work. At one point (when the Sound Manager first came out) it was still possible to call the original SysBeep() code. At least, if "System Beep" was the system beep sound, then SysBeep() would use its old code rather than calling the Sound Manager. In today's system software, however, there is an actual sound called "System Beep" and it gets played by the Sound Manager if it is the selected system beep sound. [Boy, this sounds like a bunch of double-talk. Is anyone able to follow this?] Presumably, if the code of the original SysBeep() routine is still in ROM, one can call it somehow, and memory will not be moved. That would solve the problem of using beep sounds while debugging code which cannot move memory. I don't know how to call the original SysBeep() code, assuming it is even possible. Can any of the experts reading this thread shed some light on the matter? Alexander Perlis, perlis_a@math.lsu.edu +++++++++++++++++++++++++++ >From robert@tbit.com (RObert Abatecola) Date: Thu, 24 Feb 94 17:55:06 PST Organization: TBIT, WMCS chat/message BBS, San Jose, CA (408)257-6225 > Well, if you're using C and System 7, you might want to look for my program > "DebugWindow 2.0". It uses AppleEvents to easily display messages in a > debugging window. Simply add DebugWindow.Lib to your project, and then you > can > do things like: > > Debug ("Just starting so-and-so routine\r"); > ..... > Debug ("Value of index is now %d\r", index); Any hints on where one might look for DebugWindow 2.0? +++++++++++++++++++++++++++ >From pjcreath@tucson.Princeton.EDU (Peter Janssen Creath) Date: Thu, 24 Feb 1994 21:10:06 GMT Organization: Princeton University In article , wrote: >Wow, good point. Any suggestions for an easy debugging tool like sysbeep()? My personal favorite is MacsBug in conjunction with Debugger() or DebugStr("\pWhatever error message I want"); And it's free...(just hit "g" to resume) And unless you're fiddling with low memory (and hosing the interrupt table) it won't crash on you... +++++++++++++++++++++++++++ >From blume@twg.com (David Blume) Date: Fri, 25 Feb 1994 16:34:03 GMT Organization: Gokuraku Videos - Wollongong Dept. tzs@u.washington.edu (Tim Smith) wrote: >One thing I found real useful for debugging was to write my own printf >that wrote directly to screen memory. ... I didn't have to >worry about memory being moved, or managers not being in the proper >state, or whatever. How did you draw characters directly to the screen without using a toolbox routine that may have moved or purged memory? Everything from DrawChar() to CopyBits() might move memory... --David +---------------------------------------------------------------+ | David Blume | "I get tired thinking of all the things I | | blume@twg.com | don't want to do." --Bukowski, _Barfly_ | +---------------------------------------------------------------+ +++++++++++++++++++++++++++ >From bc@wetware.com (monsieur HAINEUX) Date: Fri, 25 Feb 1994 19:20:09 GMT Organization: /usr/local/lib/rn/organization |In article , wrote: |>Wow, good point. Any suggestions for an easy debugging tool like sysbeep()? Use DebugStr(). Unless there's a reason you can't use MacsBug[1], it works like a champ, and you get more feedback than SysBeep. If you're REALLY clever, you can use a macro that includes an #ifdef _DEBUG_ to automatically make the DebugStr's go away for production code. bill coderre [1] Yes, there are cases where you cannot use MacsBug. Pray that they never catch up to you. +++++++++++++++++++++++++++ >From mahboud@aggroup.com (Mahboud Zabetian) Date: Fri, 25 Feb 1994 12:16:16 -0800 Organization: AG Group, Inc. In article , bc@wetware.com (monsieur HAINEUX) wrote: > |In article , wrote: > |>Wow, good point. Any suggestions for an easy debugging tool like sysbeep()? > > Use DebugStr(). Unless there's a reason you can't use MacsBug[1], it > works like a champ, and you get more feedback than SysBeep. > I do use Debugger() and DebugStr(). (In fact I also have use my own DebugNum(), DebugHexNum() DebugBuffStr()....). Yet there have been times that a SysBeep() is best. For example: A customer complains that our applications doesn't do x. I look and look and look and look at the code and wonder: does it get to x and doesn't execute it, or does it execute x and x is the problem, or is this user on drugs since the code is OBVIOUSLY correct? (I don't write buggy code :-) Well, I add a quick SysBeep() before x and in x. Then I send it to the customer (who may or may not have MacsBug or who may or may not know what to do when in MacsBug) and ask him: "Does it beep when you try it? Once or twice?" You see, a Debugger() call would probably have been more of a hassle. -mahboud ps. My favorite bug: handle = GetResource(.....); if (handle = nil) { // resource is there so do somthing with it. } My next favorite bug: Calling InvalRect without a valid GrafPort set. And: SetPort(window); // where window is a random, garbage value on the stack - ------------------------------------------------------------- Mahboud Zabetian mahboud@aggroup.com ag group, inc. 2540 camino diablo, suite 200 walnut creek, ca 94596 510-937-7900 voice 510-937-2479 fax 510-937-6704 ara ftp.aggroup.com anonymous ftp +++++++++++++++++++++++++++ >From bc@wetware.com (monsieur HAINEUX) Date: Fri, 25 Feb 1994 21:34:25 GMT Organization: /usr/local/lib/rn/organization In article bc@wetware.com (monsieur HAINEUX) writes: ||In article , wrote: ||>Wow, good point. Any suggestions for an easy debugging tool like sysbeep()? | |Use DebugStr(). Unless there's a reason you can't use MacsBug[1], it |works like a champ, and you get more feedback than SysBeep. | |If you're REALLY clever, you can use a macro that includes an #ifdef |_DEBUG_ to automatically make the DebugStr's go away for production |code. | |bill coderre |[1] Yes, there are cases where you cannot use MacsBug. Pray that they |never catch up to you. Think Reference reminded me that DebugStr dumps you into the debugger, but you can put a string like "Entering BugVille;g" and the semicolon allows you to load up the rest of the string with MacsBug commands. In this case, the screen will flicker briefly while Macsbug writes the line, then the program will resume. bill coderre "Hard Problems made simple -- and vice versa" -- corporate motto of Symbolics +++++++++++++++++++++++++++ >From mxmora@unix.sri.com (Matt Mora) Date: 25 Feb 1994 10:08:13 -0800 Organization: SRI International, Menlo Park, CA In article <1994Feb25.163403.14920@twg.com> blume@twg.com (David Blume) writes: >tzs@u.washington.edu (Tim Smith) wrote: >>One thing I found real useful for debugging was to write my own printf >>that wrote directly to screen memory. ... I didn't have to >>worry about memory being moved, or managers not being in the proper >>state, or whatever. > >How did you draw characters directly to the screen without using a toolbox >routine that may have moved or purged memory? Everything from DrawChar() >to CopyBits() might move memory... He probably twiddled the bits directly. Which is why he said he was using a 5 x 7 character set. He set each bit in the screen's bitmap himself. Cool. Xavier -- ___________________________________________________________ Matthew Xavier Mora Matt_Mora@qm.sri.com SRI International mxmora@unix.sri.com 333 Ravenswood Ave Menlo Park, CA. 94025 +++++++++++++++++++++++++++ >From monroe@teleport.com (Monroe Williams) Date: 25 Feb 1994 17:00:18 -0800 Organization: Teleport - Portland's Public Access (503) 220-1016 In article <2kjhqi$2n70@te6000.otc.lsu.edu>, Alexander Perlis wrote: [...] >Presumably, if the code of the original SysBeep() routine is still in ROM, >one can call it somehow, and memory will not be moved. That would solve >the problem of using beep sounds while debugging code which cannot move >memory. I don't know how to call the original SysBeep() code, assuming it >is even possible. Can any of the experts reading this thread shed some >light on the matter? I doubt very much that any of the newer machines have the old SysBeep code in them. As you said, it's been done through the sound manager for quite some time now. However... It should be possible to find the startup chime code in the ROMs. I seem to remember a little utility that plays the startup chime and various error tones, apparently using the ROMs to do it. Does anybody out there know how this is done? There are a couple of really disturbing sounds a Mac can make (like when it fails the hardware RAM diagnostic) that would definitely get your attention. I can't imagine these ROM routines would even require the memory manager, much less move memory. BTW (for the curious), on my SE/30 you can hear the error tones by pressing the interrupt button on the programmer's switch while the machine is doing the initial memory tests when you first switch it on. I don't know if this trick works on newer machines that have the nicer sounding startup chime, though. - monroe -- monroe@teleport.COM Public Access User --- Not affiliated with TECHbooks Public Access UNIX and Internet at (503) 220-0636 (1200/2400, N81) +++++++++++++++++++++++++++ >From monroe@teleport.com (Monroe Williams) Date: 25 Feb 1994 17:22:04 -0800 Organization: Teleport - Portland's Public Access (503) 220-1016 In article , monsieur HAINEUX wrote: >In article bc@wetware.com (monsieur HAINEUX) writes: >|If you're REALLY clever, you can use a macro that includes an #ifdef >|_DEBUG_ to automatically make the DebugStr's go away for production >|code. Digressing just a bit... It's pretty simple to make up a version of assert() that uses DebugStr. (Start with the assert.h that comes with your development environment. It's almost always implemented as a macro.) With a few preprocessor tricks, it will give you the file name and line number, as well as the expression inside the assertion. Real handy, especially for porting code from unix that's full of asserts, when you're not using console I/O. - monroe -- monroe@teleport.COM Public Access User --- Not affiliated with TECHbooks Public Access UNIX and Internet at (503) 220-0636 (1200/2400, N81) +++++++++++++++++++++++++++ >From lewistot@netcom.com (John Lewis) Date: Sat, 26 Feb 1994 04:22:56 GMT Organization: NETCOM On-line Communication Services (408 241-9760 guest) Mahboud Zabetian (mahboud@aggroup.com) wrote: : SysBeep() may move memory and could potentially make dereferenced handles : invalid! You mean you don't lock your handles BEFORE you dereference them? : This is a hard one to chase down, since you now have another bug added to : whatever bug you were originally looking for. Surround your dereferences with a LockHandle/UnlockHandle pair. This is not only good programming practice, but it will also solve the problem of SysBeep moving things around. -- - ------------------------------------------------------------------------- John "I'ld rather be skydiving" Lewis|#include "standard .sig BS" |Witty | lewistot@netcom.com <- prefered |Blue Skies to all skydivers.|text | jlewis@maxis.com <- work |USPA 87419, C-22826 |picture| lewistotle@aol.com | |comming| +++++++++++++++++++++++++++ >From kledbetter@aol.com (KLedbetter) Date: 26 Feb 1994 13:25:02 -0500 Organization: America Online, Inc. > Debug ("Just starting so-and-so routine\r"); > ..... > Debug ("Value of index is now %d\r", index); Any hints on where one might look for DebugWindow 2.0? - -------- Robert -- it's available on Compuserve in the MacDev forum, and on America Online in the Mac Developers area. It works really nice .. you can also do Hex dumps to the window (ie: DebugHexDump (myBuffer, 1024)) and then print out the window's contents, save as a teachtext document, etc.. Keith +++++++++++++++++++++++++++ >From casgrain@ERE.UMontreal.CA (Casgrain Philippe) Date: Sat, 26 Feb 1994 19:53:59 GMT Organization: Universite de Montreal >> Debug ("Just starting so-and-so routine\r"); >> ..... >> Debug ("Value of index is now %d\r", index); > >Any hints on where one might look for DebugWindow 2.0? > it's available on Compuserve in the MacDev forum, and on America Online in >the Mac Developers area. It works really nice .. you can also do Hex dumps to >the window (ie: DebugHexDump (myBuffer, 1024)) and then print out the window's >contents, save as a teachtext document, etc.. > Any idea where we could find it on the Internet? could somebody post it? Philippe -- -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= Philippe Casgrain Etudiant-Chercheur Casgrain@ERE.UMontreal.CA Departement des Sciences Biologiques Universite de Montreal "Imitation is the sincerest form of flattery" +++++++++++++++++++++++++++ >From kledbetter@aol.com (KLedbetter) Date: 27 Feb 1994 01:35:01 -0500 Organization: America Online, Inc. > Any idea where we could find it on the Internet? could somebody post it? Philippe - ------- I'm looking into getting it up on the Internet now...I'll post a message as soon as I get it out there... keith +++++++++++++++++++++++++++ >From tzs@u.washington.edu (Tim Smith) Date: 1 Mar 1994 03:24:34 GMT Organization: University of Washington School of Law, Class of '95 In article <2kleqd$51q@unix.sri.com>, Matt Mora wrote: >He probably twiddled the bits directly. Which is why he said he was using >a 5 x 7 character set. He set each bit in the screen's bitmap himself. >Cool. Actually, I said 3x5. That way, with one pixel between consecutive characters, memory manipulation only had to go down to the nibble level. On a 640x480 display, with 2 lines of leading between lines, I could get 160 columns and 68 rows. In addition to drawing the character, I would also draw an underline three lines below the character, and erase the two lines immediately below the character. That way, you could tell which of the 68 rows was the last one drawn--it was the one that was underlined. That way you can tell where you are as more than 68 rows are printed and they start to wrap. I also had an end of line marker so you could tell on a row which characters belonged to that row, and which were left over from the 68th previous printf, the 136th previous printf, etc. The hardest part was coming up with a 3x5 'M' that looks different than a 3x5 'N'! Here's my character set, in case anyone is curious. struct OneChar { char data[5]; /* the data for a character */ }; struct OneChar CharData[] = { {5,2,5,2,5}, /* non-existant char */ {2,5,7,5,5}, /* 1 A */ {6,5,6,5,6}, {7,5,4,5,7}, {6,5,5,5,6}, {7,4,6,4,7}, {7,4,6,4,4}, {7,4,5,5,7}, /* 7 G */ {5,5,7,5,5}, {7,2,2,2,7}, {3,1,1,5,7}, {4,5,6,5,5}, {4,4,4,4,7}, {5,7,5,5,5}, {5,7,7,7,5}, {2,5,5,5,2}, /* 15 O */ {7,5,7,4,4}, {2,5,5,7,3}, {6,5,7,6,5}, {3,4,6,1,7}, {7,2,2,2,2}, {5,5,5,5,7}, {5,5,5,5,2}, {5,5,5,7,5}, {5,2,2,2,5}, {5,5,2,2,2}, {7,1,2,4,7}, /* 26 Z */ {3,5,5,5,6}, /* 27 0 */ {2,6,2,2,7}, {7,5,2,4,7}, {7,1,3,1,7}, {5,5,7,1,1}, {7,4,7,1,7}, {4,4,7,5,7}, {7,1,1,2,2}, {7,5,7,5,7}, {7,5,7,1,1}, /* 36 9 */ {0,0,0,0,0}, /* 37 space */ {2,2,2,0,2}, /* ! */ {5,5,0,0,0}, /* " */ {5,7,5,7,5}, /* 40 # */ {7,6,2,3,7}, /* $ */ {3,3,2,6,6}, /* % */ {6,5,2,5,7}, /* & */ {2,2,0,0,0}, /* ' */ {2,4,4,4,2}, /* 45 ( */ {2,1,1,1,2}, /* ) */ {5,2,7,2,5}, /* * */ {0,2,7,2,0}, /* + */ {0,0,0,1,3}, /* , */ {0,0,7,0,0}, /* 50 - */ {0,0,0,6,6}, /* . */ {1,1,2,2,4}, /* / */ {6,6,0,6,6}, /* : */ {6,6,0,2,6}, /* ; */ {1,2,4,2,1}, /* 55 < */ {0,7,0,7,0}, /* = */ {4,2,1,2,4}, /* > */ {6,1,2,0,2}, /* ? */ {6,4,4,4,6}, /* [ */ {4,4,2,2,1}, /* 60 \ */ {3,1,1,1,3}, /* ] */ {2,5,0,0,0}, /* ^ */ {0,0,0,0,7}, /* _ */ {4,2,0,0,0}, /* ^ */ {3,2,4,2,3}, /* 65 { */ {2,2,2,2,2}, /* | */ {6,2,1,2,6}, /* } */ {4,7,1,0,0}, /* ~ */ {0,3,5,6,3}, /* @ */ {7,7,7,7,7} /* end of line marker */ } --Tim Smith +++++++++++++++++++++++++++ >From ez006626@othello.ucdavis.edu (David Xavier Clancy) Date: Tue, 1 Mar 1994 09:51:29 GMT Organization: University of California, Davis I thought the accepted thing was to use FlashMenuBar It is not auditory, but if you are looking at the screen, it does the trick. Also, I'm pretty sure DebugWindow, (i get the name right?) mentioned in other posts is at sumex. --xav +++++++++++++++++++++++++++ >From philip@concave.cs.wits.ac.za (Philip Machanick) Date: Tue, 01 Mar 1994 08:51:39 +0200 Organization: Computer Science Dept, U of Witwatersrand In article , lewistot@netcom.com (John Lewis) wrote: > Surround your dereferences with a LockHandle/UnlockHandle pair. This is > not only good programming practice, but it will also solve the problem > of SysBeep moving things around. No it's not. Much better practice is oldstate = HGetState(h); HLock(h); ...do something assuming h can't move... HSetState(h, oldstate); otherwise you could end up unlocking a handle that the code that called the current routine still expects to have locked. In any case: there are situations where you don't want to lock a handle and to put the locking code in just because you are debugging is not a good solution. -- Philip Machanick philip@concave.cs.wits.ac.za Department of Computer Science, University of the Witwatersrand 2050 Wits, South Africa phone 27(11)716-3309 fax 27(11)339-7965 +++++++++++++++++++++++++++ >From walrathw@rferl.org (WalrathW) Date: 3 Mar 94 09:22:38 -0500 Organization: RFE/RL Inc. In article lewistot@netcom.com (John Lewis) writes: > Mahboud Zabetian (mahboud@aggroup.com) wrote: > : SysBeep() may move memory and could potentially make dereferenced handles > : invalid! > > You mean you don't lock your handles BEFORE you dereference them? > > : This is a hard one to chase down, since you now have another bug added to > : whatever bug you were originally looking for. > > Surround your dereferences with a LockHandle/UnlockHandle pair. This is > not only good programming practice, but it will also solve the problem > of SysBeep moving things around. > -- I would disagree that it's good programming practice to just surround every handle with HLock/HUnlock calls. Those calls take time and if they aren't absolutely necessary, then you shouldn't use them. HLock(myHandle); ((MyStruct*)*myHandle)->myLong = 10; HUnlock(myHandle); nahhh? > --------------------------------------------------------------------------- > John "I'ld rather be skydiving" Lewis|#include "standard .sig BS" |Witty | > lewistot@netcom.com <- prefered |Blue Skies to all skydivers.|text | > jlewis@maxis.com <- work |USPA 87419, C-22826 |picture| > lewistotle@aol.com | |comming| maxis.com, is that the Simulation Games company? ______o0o______ Wayne Walrath RFE/RL Inc. +++++++++++++++++++++++++++ >From tgreen@ersys.edmonton.ab.ca (Terry Greeniaus) Date: Mon, 07 Mar 94 16:13:55 MST Organization: Edmonton Remote Systems #2 > In article , > Mahboud Zabetian wrote: > > >> Wow, good point. Any suggestions for an easy debugging tool like sysbeep( Well, you could use FlashMenuBar(), but I'm not sure whether it messes with memory or not. -- Terry Greeniaus tgreen@ersys.edmonton.ab.ca Edmonton Remote Systems Serving Edmonton/Northern Alberta since 1982 +++++++++++++++++++++++++++ >From mxmora@unix.sri.com (Matt Mora) Date: 10 Mar 1994 09:00:10 -0800 Organization: SRI International, Menlo Park, CA In article tgreen@ersys.edmonton.ab.ca (Terry Greeniaus) writes: >> In article , >> Mahboud Zabetian wrote: > >Well, you could use FlashMenuBar(), but I'm not sure whether it messes >with memory or not. Not unless you are sure the gworld is valid ( ie the one with the menubar) before you call it as another poster had mentioned. Xavier -- ___________________________________________________________ Matthew Xavier Mora Matt_Mora@qm.sri.com SRI International mxmora@unix.sri.com 333 Ravenswood Ave Menlo Park, CA. 94025 +++++++++++++++++++++++++++ >From mbabramo@unix.amherst.edu (MICHAEL BERNARD ABRAMOWICZ) Date: 11 Mar 1994 20:15:35 -0500 Organization: Amherst College, Amherst MA, USA > Well, you could use FlashMenuBar(), but I'm not sure whether it messes > with memory or not. This is exactly the solution. FlashMenuBar() does NOT move memory. > -- > Terry Greeniaus tgreen@ersys.edmonton.ab.ca > Edmonton Remote Systems Serving Edmonton/Northern Alberta since 1982 Michael Abramowicz Amherst College Writer, Inside Macintosh: Memory, More Macintosh Toolbox, Sound +++++++++++++++++++++++++++ >From mahboud@aggroup.com (Mahboud Zabetian) Date: Sun, 13 Mar 1994 23:34:29 -0800 Organization: AG Group, Inc. In article <2lr53n$lr3@amhux3.amherst.edu>, mbabramo@unix.amherst.edu (MICHAEL BERNARD ABRAMOWICZ) wrote: > > Well, you could use FlashMenuBar(), but I'm not sure whether it messes > > with memory or not. > > This is exactly the solution. FlashMenuBar() does NOT move memory. > > > -- > > Terry Greeniaus tgreen@ersys.edmonton.ab.ca > > Edmonton Remote Systems Serving Edmonton/Northern Alberta since 1982 > > Michael Abramowicz > Amherst College > Writer, Inside Macintosh: Memory, More Macintosh Toolbox, Sound I have tried to use FlashMenuBar in place of SysBeep. I don't find it as useful as SysBeep though. It is very hard to miss a SysBeep, but FlashMenuBar is easy to miss. Especially if you have a faster machine. -mahboud - ------------------------------------------------------------- Mahboud Zabetian mahboud@aggroup.com ag group, inc. 2540 camino diablo, suite 200 walnut creek, ca 94596 510-937-7900 voice 510-937-2479 fax 510-937-6704 ara ftp.aggroup.com anonymous ftp +++++++++++++++++++++++++++ >From Greg_Marriott@genmagic.com (Greg Marriott) Date: Mon, 14 Mar 1994 01:55:17 -0800 Organization: General Magic, Inc. mbabramo@unix.amherst.edu (MICHAEL BERNARD ABRAMOWICZ) wrote: > > Well, you could use FlashMenuBar(), but I'm not sure whether it messes > > with memory or not. > > This is exactly the solution. FlashMenuBar() does NOT move memory. Wrong. This took me less than a minute to check out. Among the calls made inside FlashMenuBar(): NewHandle() and SetHandleSize(). -- Greg Marriott Just Some Guy General Magic, Inc. Disclaimer: My opinions are not necessarily the same as General Magic's. (can a company even HAVE an opinion?) --------------------------- >From perlis_a@math.lsu.edu (Alexander Perlis) Subject: Improving DrawText speed (Was: Color Terminal Emulator) Date: 11 Mar 1994 18:28:27 GMT Organization: Louisiana State University InterNetNews Site In article trygve@apple.com (Trygve Isaacson) writes: > > 2) Optimize out whitespace: move the pen instead of drawing blanks. Of > course, this assumes you can calculate the character width ahead of time, > which assumes you're using a monospaced font. Note that boldface throws a > wrench in things unless your font's bold maintains the same character width > as plain, as does our Noiro font shipped with the SNA ps emulators. > > Trygve Isaacson > SNA ps engineer > Apple Computer, Inc. I thought the built-in QuickDraw routines for drawing text simply ASSUME that the space character (ASCII 32) in every font is truly a space and simply move the pen without drawing anything when in srcOr mode. Of course, if your font is monospaced and you have a bunch of spaces, it might be faster to just skip over that than letting QuickDraw move the pen a bunch of times, but I don't believe that the speedup is too significant in the sense that one should worry more about speeding up the drawing of actual text than speeding up the movement of the pen over empty regions. If you put a graphic character in position 32 of a font, it will NOT be displayed. As far as I can tell, this behavior, and a few other subleties involving graphic characters in the control positions of a font, characters 0 through 31, have never been fully documented or explained by Apple. Please correct me if I'm wrong and point me in the direction of such documentation. I got around the problems in QuickDraw by writing a complete replacement for the text drawing system (not too difficult since I only use monospaced fonts in terminal emulation) which can handle fonts of 256 true graphic characters. This solution proved faster than using two Macintosh fonts with 128 characters each to simulate a 256-character font and swapping between the two fonts all the time. Incidentally, I never understood WHY QuickDraw has trouble drawing text in srcCopy mode. The only slowdown should come when it has to draw a space, since now it must actually erase the rectangle rather than simply moving the pen. But that should not account for the major difference in speed between srcOr and srcCopy. Can someone at Apple explain this? Alexander Perlis perlis_a@math.lsu.edu --------------------------- >From atotic@void.ncsa.uiuc.edu (Alexsander Totic) Subject: Interface guidelines for extra program files Date: 16 Mar 94 16:36:40 GMT Organization: University of Illinois at Urbana I am building a program that creates and uses several external files besides preferences. I have always disliked any external file approaches, but this time I have to store data in this way. I was wandering what the Apple's recommendation for storing of these files are: should application have its own folder somewhere on a disk, or in a system folder, or spread around through user preferences. Allowing user to specify location of external folder allows multiple users to start up an application by clicking on their preferences file, and have everything work fine. But it also confuses them, especially when there are many external files. There is no right solution, so I would like to skip the responsibility, and follow the guidelines. Aleks -- Aleksandar Totic -- MacMosaic developer -- atotic@ncsa.uiuc.edu Software Development Group National Center for Supercomputing Applications http://www.ncsa.uiuc.edu/SDG/People/atotic/alex.html +++++++++++++++++++++++++++ >From pcastine@jake.prz.tu-berlin.de (Peter Castine) Date: Thu, 17 Mar 1994 20:57:38 GMT Organization: PRZ TU-Berlin Alexsander Totic writes: >I am building a program that creates and uses several external files besides >preferences. I have always disliked any external file approaches, but >this time I have to store data in this way. I was wandering what the >Apple's recommendation for storing of these files are: should application >have its own folder somewhere on a disk, or in a system folder, or spread >around through user preferences. > >Allowing user to specify location of external folder allows multiple users >to start up an application by clicking on their preferences file, and have >everything work fine. But it also confuses them, especially when there are >many external files. > >There is no right solution, so I would like to skip the responsibility, and >follow the guidelines. > The only guideline is "Don't put user files in the same folder as the application." This is because the application might well be on a file server and the user would probably not have write access to that folder. I think the best solution is to do what QuickMail (and several other programs) does: instead of a single file in the user's Preferences folder, it creates a ' Stuff' folder in the Preferences folder, and dumps everything in there. Make sure to use the _FindFolder trap (if it's available) when looking for the Prefs folder. It is *NOT* called 'Preferences' on many Macs. -- Peter Castine | One child is shot every two hours pcastine@jake.kgw.tu-berlin.de | in the U.S.A. | Thank you for blocking gun control, | N.R.A. --------------------------- >From jafl@cco.caltech.edu (John Lindal) Subject: Intermixing graphics and text Date: 15 Mar 1994 01:35:47 GMT Organization: California Institute of Technology, Pasadena Has anyone written any straight code or TCL classes that allow pictures and text to be intermixed? Of these, is there anyone willing to share this? (or sell it for that matter?) Thanks. John Lindal +++++++++++++++++++++++++++ >From thunderone@delphi.com Date: Tue, 15 Mar 94 02:40:05 -0500 Organization: Delphi (info@delphi.com email, 800-695-4005 voice) John Lindal writes: >Has anyone written any straight code or TCL classes that allow pictures >and text to be intermixed? Of these, is there anyone willing to share this? >(or sell it for that matter?) If you want to use TextEdit, it's pretty simple to do. Here's how I do it. Note that pictHandle is an array containing PICT resources (surprise!) and pictPositions is an array that holds the number of the character that the lower left corner of the picture is anchored on. Point tPoint; PicHandle WhiteNoise; short i; Rect theRect; / GrafPtr old; CGrafPtr theGraf=(CGrafPtr)theWindow; SetPort(thePort); if(numPicts){ for(i=1;i<=numPicts;i++){ WhiteNoise=pictHandle[i]; if(!WhiteNoise) return; tPoint=TEGetPoint(pictPositions[i],theTE); HLockHi((Handle)WhiteNoise); theRect=(**WhiteNoise).picFrame; theRect.right=tPoint.h+(theRect.right-theRect.left); theRect.top=tPoint.v-(theRect.bottom-theRect.top); theRect.left=tPoint.h; theRect.bottom=tPoint.v; UQD::KillClip(); ClipRect(&teSquare);//(**theTE).viewRect DrawPicture(WhiteNoise,&theRect); if(pictPositions[i]>=(**theTE).selStart&&pictPositions[i]<(**theTE). selEnd){ if(UQD::BitDepth()>1){ PenMode(adMin); RGBForeColor(&(**(GVarHandle)theGraf->grafVars).rgbHiliteCol or); BackColor(blackColor); PaintRect(&theRect); }else{ InvertRect(&theRect); } } ForeColor(blackColor); BackColor(whiteColor); UQD::RestoreClip(); HUnlock((Handle)WhiteNoise); } } Chris - Chris Thomas, Delphi ICONtact Developer Database Librarian thunderone@delphi.com --------------------------- >From ldo@waikato.ac.nz (Lawrence D'Oliveiro, Waikato University) Subject: Let's kill 24-bit mode! (was Re: Let's kill System 6!) Date: 14 Mar 94 18:31:16 +1300 Organization: University of Waikato, Hamilton, New Zealand OK, let's start a new version of this thread, shall we? With more and more machines running with more than 8MB of RAM, is it worth still testing your code to make sure it works in 24-bit mode? It's so much easier leaving out all those StripAddress calls, rather than trying to remember when you need them and when you don't, don't you think? I've been running a home machine in 32-bit mode for close to 3 years now. First it was an LC with 10MB, now it's a C650 with 16MB. And Godot, my long- awaited, brand-spanking-new 840AV at work, couldn't run in 24-bit mode if I wanted it to. So what do other people think? Is it time to declare 24-bit mode dead yet...? Lawrence D'Oliveiro fone: +64-7-856-2889 Info & Tech Services Division fax: +64-7-838-4066 University of Waikato electric mail: ldo@waikato.ac.nz Hamilton, New Zealand 37^ 47' 26" S, 175^ 19' 7" E, GMT+13:00 +++++++++++++++++++++++++++ >From jwbaxter@olympus.net (John W. Baxter) Date: Mon, 14 Mar 1994 09:18:43 -0800 Organization: Internet for the Olympic Peninsula In article <1994Mar14.183116.26366@waikato.ac.nz>, ldo@waikato.ac.nz (Lawrence D'Oliveiro, Waikato University) wrote: > So what do other people think? Is it time to declare 24-bit mode dead yet...? If you like, and test for the machine being in 24-bit mode at the start of your code, and alert and exit gracefully. I don't mind being told gently that your code won't work on my secondary machine (a 4 meg Mac Plus). I do mind if it crashes. And I mind a WHOLE LOT if it corrupts the disk while/before crashing, or (worse) corrupts the disk without crashing. Same with my primary machine, in the once-every-6-months situation where I set it to 24-bit mode for some odd reason. With some of the newest machines not being able to run in 24-bit mode, the time is approaching, but it may not be here yet. -- John Baxter Port Ludlow, WA, USA [West shore, Puget Sound] jwbaxter@pt.olympus.net +++++++++++++++++++++++++++ >From u9119523@sys.uea.ac.uk (Graham Cox) Date: Tue, 15 Mar 1994 17:41:52 GMT Organization: School of Information Systems, UEA, Norwich In article <1994Mar14.183116.26366@waikato.ac.nz>, ldo@waikato.ac.nz (Lawrence D'Oliveiro, Waikato University) wrote: > OK, let's start a new version of this thread, shall we? > > With more and more machines running with more than 8MB of RAM, is it worth > still testing your code to make sure it works in 24-bit mode? It's so much > easier leaving out all those StripAddress calls, rather than trying to remember > when you need them and when you don't, don't you think? > > I've been running a home machine in 32-bit mode for close to 3 years now. > First it was an LC with 10MB, now it's a C650 with 16MB. And Godot, my long- > awaited, brand-spanking-new 840AV at work, couldn't run in 24-bit mode if I > wanted it to. > > So what do other people think? Is it time to declare 24-bit mode dead yet...? > > Lawrence D'Oliveiro fone: +64-7-856-2889 > Info & Tech Services Division fax: +64-7-838-4066 > University of Waikato electric mail: ldo@waikato.ac.nz > Hamilton, New Zealand 37^ 47' 26" S, 175^ 19' 7" E, GMT+13:00 Am I missing something vital here? I have never used StripAddress in any program I've ever written and they all work in 24 or 32-bit mode. Either what I'm doing is not very advanced compared to yours or you aren't doing things the compatible way! I don't want to dump on you about this without knowing the facts- I therefore assume the former (?). I believe that addresses/pointers are always valid in whatever mode and OF COURSE you never try to set the high byte of a handle right? - ------------------------------------------------------------------------ Love & BSWK, Graham -Everyone is entitled to their opinion, no matter how wrong they may be... - ------------------------------------------------------------------------ +++++++++++++++++++++++++++ >From t-gaul@i-link.com (Troy Gaul) Date: Tue, 15 Mar 1994 17:10:35 -0600 Organization: I-Link, Ltd. In article , u9119523@sys.uea.ac.uk (Graham Cox) wrote: > In article <1994Mar14.183116.26366@waikato.ac.nz>, ldo@waikato.ac.nz > (Lawrence D'Oliveiro, Waikato University) wrote: > > > OK, let's start a new version of this thread, shall we? > > > > With more and more machines running with more than 8MB of RAM, is it worth > > still testing your code to make sure it works in 24-bit mode? It's so much > > easier leaving out all those StripAddress calls, rather than trying to remember > > when you need them and when you don't, don't you think? > > > > I've been running a home machine in 32-bit mode for close to 3 years now. > > First it was an LC with 10MB, now it's a C650 with 16MB. And Godot, my long- > > awaited, brand-spanking-new 840AV at work, couldn't run in 24-bit mode if I > > wanted it to. > > > > So what do other people think? Is it time to declare 24-bit mode dead yet...? > > Am I missing something vital here? I have never used StripAddress in any > program I've ever written and they all work in 24 or 32-bit mode. Either > what I'm doing is not very advanced compared to yours or you aren't doing > things the compatible way! I don't want to dump on you about this without > knowing the facts- I therefore assume the former (?). I believe that > addresses/pointers are always valid in whatever mode and OF COURSE you > never try to set the high byte of a handle right? There are cases where you must call StripAddress for a program to function correctly in all 'modes'. It is possible that you haven't run across them. One case in point is when you are manually switching the processor's addressing modes (like, when working with directly accessing data in a GWorld PixMap). Since the PixMap may be stored on a NuBus board's memory (our of 24-bit range), you should switch to 32-bit mode to access the data (and back when you're done). If you have a pointer in a local variable from before you switched out of 24-bit, it is possible this pointer has some high bits being used, so you should strip it if you intend to dereference it from 32-bit mode. Moral is: when you might be changing modes, you should be careful. Or something like that. :) _troy //////// //////___Troy Gaul_________________________t-gaul@i-link.com__ // // // I-Link, Ltd. ; West Des Moines, Iowa // // // // "Iungo ergo sum." (I-Link, therefore I am.) // // //////________________________________________________________ // >From DACRXL01.OURX124@tcp30.dx.deere.com (Juan Ingles) Subject: Let's kill 24-bit mode! (was Re: Let's kill System 6!) Date: Tue, 15 Mar 1994 23:47:30 GMT Organization: Proteus Ventures, Inc. In article <1994Mar14.183116.26366@waikato.ac.nz> ldo@waikato.ac.nz (Lawrence D'Oliveiro, Waikato University) writes: > With more and more machines running with more than 8MB of RAM, is it worth > still testing your code to make sure it works in 24-bit mode? It's so much > easier leaving out all those StripAddress calls, rather than trying to remember > when you need them and when you don't, don't you think? Huh? StripAddress? What's that? :-) :-) Juan Ingles -- Proteus Ventures, Inc. - Computer Software Consulting and Development 1514 Oriole Ave * Waterloo, IA 50701 * (319) 232-0985 +++++++++++++++++++++++++++ >From sw@network-analysis-ltd.co.uk (Sak Wathanasin) Date: Wed, 16 Mar 94 00:15:54 GMT Organization: Network Analysis Ltd In article (comp.sys.mac.programmer), u9119523@sys.uea.ac.uk (Graham Cox) writes: > ... I believe that > addresses/pointers are always valid in whatever mode and OF COURSE you > never try to set the high byte of a handle right? You don't have to: the resource manager will happily set them for you, for example. Most of the time it doesn't matter, but there are times when it does (like when you call a code resource loaded with the RM and the CR turns on 32-bit mode - your return addreses on the stack become instant garbage). There's a tech note that tells you when StripAdress is necessary; can't remember what it's called off the top of my head. Sak Wathanasin Network Analysis Limited 178 Wainbody Ave South, Coventry CV3 6BX, UK Internet: sw@network-analysis-ltd.co.uk uucp: ...!uknet!nan!sw AppleLink: NAN.LTD Phone: (+44) 203 419996 Mobile:(+44) 850 587411 Fax: (+44) 203 690690 --------------------------- >From bsc@oui.com (Bill Stewart-Cole) Subject: Let's kill system 6! Date: 20 Feb 1994 13:12:15 -0600 Organization: Odyssey Ultraware Inc St Louis, MO The whole discussion on supporting system 6 has spurred some thoughts: Would not Mac developers benefit by a 100% move to system 7? Would not Mac users benefit by upgrading to 7 and Macs that can run it well? It is a royal pain to support BOTH the full features of 7, and system 6. I have taken 2 tracks: 1. if the program specifically calls for features of 7, I check for it and politely quit if I don't have it. 2. If the program can be used just fine without 7-specific features, I use all the system 6 versions and let the program crash on the rare 512k (not 512ke) running 4.1. The one time I tried to develop a program for an either/or operation, the result was a confusing program to debug and a program far too big. And a nervous tic:). We'd all make smaller, clearer, and less bug-prone code if we stuck to one set of system features. Programs would get out faster. Money would flow in for programs sooner. We'd have fewer ulcers. On the user side, it's important to consider who is still using system 6 and why. They are essentially 2 types: 1. People who have a fixed function for their Mac that works well and can be done with 6. 2. People who would do better running 7 on a faster Mac. In the first group, they aren't buying software. In the second, they are ready to move to 7 with the slightest nudge. A //ci-class Mac is a fine platform for 7, and the 5 machines in that general performance range are breaking below $700 on the used market. Even if Joe Plus User won't bite on a $2000 PDM PowerMac, he is not unlikely to see the used //ci's and //cx's and LC3's being dumped to upgrade by other users who want faster boxes as tempting. The increased pressure in that direction of 7-only software (i.e. requiring a good machine for running 7) will make for a user base with more compatibility, more power, and less ghettoizing of users. Anyway, I think it is a positive step for developers to move away from supporting system 6 because of the good it will do to get everyone running 7, both for developers and for users. +++++++++++++++++++++++++++ >From rrwood@r-node.io.org (Roy Wood) Date: 21 Feb 1994 10:41:47 -0500 Organization: Internex Online (io.org) Data: 416-363-3783 Voice: 416-363-8676 Another group of users stuck with sloooooooow system 6 machines are students and teachers at public schools. I'd love to upgrade our lab to faster machines, but there's no way our budget can afford it. This is not such a huge problem, in terms of the thread being discussed, since we're doing mostly word processing and other mundane things, and we're hardly likely to rush out and invest in any bleeding-edge killer apps anyway. -Roy +++++++++++++++++++++++++++ >From time@garnet.msen.com (Tim Endres) Date: 22 Feb 1994 17:32:28 GMT Organization: Msen, Inc. -- Ann Arbor, MI (account info: +1 313 998-4562) Bill Stewart-Cole (bsc@oui.com) wrote: : The whole discussion on supporting system 6 has spurred some thoughts: : Would not Mac developers benefit by a 100% move to system 7? : Would not Mac users benefit by upgrading to 7 and Macs that can run it well? This is a marketing decision, not a engineering decision. Perform your own market analysis and make a business decision. That is what most developers do... +++++++++++++++++++++++++++ >From wbostow@hounix.org (Wayne Bostow) Date: Thu, 24 Feb 1994 15:09:52 GMT Organization: Houston UNIX Users Group (HOUNIX), Houston, TX : Would not Mac developers benefit by a 100% move to system 7? Well, not me! I am ticked at Apple for allowing no upgrade path from MPW 1.0. I bought everything in '87 for under $300. I did not get several upgrades because APPLE said not to unless you had a machine to handle it. My current version will not even launch under sys 7. To get everything now is about $1000 plus a new hard drive and more memory. As an assembly programmer, I see most of the improvements as clutter. -- __________________________________________________________ Wayne Bostow "The HangulMan" 10558 Alcott, Houston, TX 77043 ph. (713)468-6546 wbostow@hounix.org +++++++++++++++++++++++++++ >From ingemar@lysator.liu.se (Ingemar Ragnemalm) Date: Fri, 25 Feb 1994 11:04:37 GMT Organization: (none) time@garnet.msen.com (Tim Endres) writes: >Bill Stewart-Cole (bsc@oui.com) wrote: >: The whole discussion on supporting system 6 has spurred some thoughts: >: Would not Mac developers benefit by a 100% move to system 7? >: Would not Mac users benefit by upgrading to 7 and Macs that can run it well? That means killing off all Macs below LC III. Plus, SE, LC, LC II, Classic, Classic II, Color Classic, PB100,Portable, perhaps even IIcx, IIsi and IIvi. All those Macs are significantly nicer with System 6. Apple has designed System 7 in a way that makes a 100% move to System 7 *impossible*. System 6 won't go away until the last of the above Macs stop working. Sure, many users will move to sys 7 even with slow Macs, usually since they are forced to, but lots of them will run system 6 until they die. And they won't die for a long time yet. You might be able to get rid of some by good trade-in offers, but even that won't help. Would you trade an SE for a LC475 at half the price? Sure? Many people will say yes, but some may think twice. Some of those Macs - especially SE - are *much* more reliable than the new ones. That's (one of the reasons) why they were so expensive. >This is a marketing decision, not a engineering decision. >Perform your own market analysis and make a business decision. >That is what most developers do... Isn't this both marketing and engineering? -- - - Ingemar Ragnemalm, PhD Image processing, Mac shareware games E-mail address: ingemar@isy.liu.se or ingemar@lysator.liu.se +++++++++++++++++++++++++++ >From j-norstad@nwu.edu (John Norstad) Date: Fri, 25 Feb 1994 13:28:09 -0600 Organization: Northwestern University In article , ingemar@lysator.liu.se (Ingemar Ragnemalm) wrote: > That means killing off all Macs below LC III. Plus, SE, LC, LC II, Classic, > Classic II, Color Classic, PB100,Portable, perhaps even IIcx, IIsi and IIvi. > All those Macs are significantly nicer with System 6. I couldn't disagree more strongly. I have a Mac Classic at home with 4 megs. It is *infinitely* nicer with System 7 than with System 6. My two kids, ages 8 and 13, who use it for homework, agree with me 100%. You need a Mac Plus or later with at least 4 megs to run System 7. It works just fine on the old Macs, and is nicer than System 6 on those Macs for exactly the same reason that it's nicer than System 6 on the newer and bigger Macs. At NU, we have completely dropped support for System 6. We tell people to get at least 4 megs and run System 7 on their old Macs. They can stay with System 6 if they wish, but if they do they are on their own, with no support from us. This was a good decision, IMHO. -- John Norstad Academic Computing and Network Services Northwestern University j-norstad@nwu.edu +++++++++++++++++++++++++++ >From DACRXL01.OURX124@tcp30.dx.deere.com (Juan Ingles) Date: Fri, 25 Feb 1994 19:31:46 GMT Organization: Proteus Ventures, Inc. In article ingemar@lysator.liu.se (Ingemar Ragnemalm) writes: > Some of those Macs - especially SE - are *much* more > reliable than the new ones. That's (one of the reasons) why they were > so expensive. Huh? Is there any evidence to support this? In my personal dealings, I have found newer machines more reliable. >That's (one of the reasons) why they were so expensive. If that were true, they would still hold a high value. I would think that profit margins, R&D, and inflation make up 99% of the reason. Juan Ingles -- Proteus Ventures, Inc. - Computer Software Consulting and Development 1514 Oriole Ave * Waterloo, IA 50701 * (319) 232-0985 -- All reality portrayed in this message is fictional. Any resemblance to any real reality, alive or dead, is purely coincidental and unintentional. +++++++++++++++++++++++++++ >From d88-jwa@mumrik.nada.kth.se (Jon Wätte) Date: 25 Feb 1994 22:08:30 GMT Organization: Royal Institute of Technology, Stockholm, Sweden In ingemar@lysator.liu.se (Ingemar Ragnemalm) writes: >That means killing off all Macs below LC III. Plus, SE, LC, LC II, Classic, >Classic II, Color Classic, PB100,Portable, perhaps even IIcx, IIsi and IIvi. My value judgement is that all of the color-capable Macs are also System-7-capable. >All those Macs are significantly nicer with System 6. Apple has designed >System 7 in a way that makes a 100% move to System 7 *impossible*. System "All those Macs" Apple is increasing its market share som 30% a year, and all macs sold the last few years have been System 7 Macs. System 6 will go away, not only because people upgrade, but because Apple sells so many more macs a year now than in 1991. Cheers, / h+ -- -- Jon W{tte, h+@nada.kth.se, Mac Hacker Deluxe -- This article printed on 100% recycled electrons. +++++++++++++++++++++++++++ >From cabu1hj@ube.ub.umd.edu Date: 26 Feb 94 22:52:01 -0500 Organization: University of Baltimore In article , ingemar@lysator.liu.se (Ingemar Ragnemalm) writes: > > [stuff deleted] > > That means killing off all Macs below LC III. Plus, SE, LC, LC II, Classic, > Classic II, Color Classic, PB100,Portable, perhaps even IIcx, IIsi and IIvi. > All those Macs are significantly nicer with System 6. I think you need to double check statements like this. Several of these systems run just fine with System 7.0, 7.0.1, & 7.1. Not with the factory shipped memory (like 3MB on the IIsi). Running them with 8MB+ isn't unrealistic given the size of current applications either. +++++++++++++++++++++++++++ >From qsi@NU91.wlink.nl (Peter Kocourek) Date: Sun, 27 Feb 1994 00:22:45 +0100 Organization: (none) Ingemar Ragnemalm wrote in a message on 25 Feb 94 IR> That means killing off all Macs below LC III. Plus, SE, LC, IR> LC II, Classic, Classic II, Color Classic, PB100,Portable, IR> perhaps even IIcx, IIsi and IIvi. All those Macs are significantly IR> nicer with System 6. Apple has designed System 7 in a way that I beg to differ. I have a IIsi here, and I don't see how running System 6 on it would make it "nicer". I'd lose aliases, drag & drop, AppleEvents (and hence AppleScript), a much better Finder, WorldScript, and Publish & Subscribe. How can the loss of these make the machine "nicer"? IR> makes a 100% move to System 7 *impossible*. System 6 won't IR> go away until the last of the above Macs stop working. Sure, IR> many users will move to sys 7 even with slow Macs, usually IR> since they are forced to, but lots of them will run system IR> 6 until they die. Oh, sure, a 100% adoption rate for System 7 won't ever happen; after all, there are still people running CP/M too. :-) But I think you are wrong with your classification of System 6 Macs; I don't know anybody running System 6 on an LC or Mac II. And System 6 is dying very quickly, now that Apple is selling huge amounts of Macs every year (perhaps as many as 4 million this year), none of which can run System 6. IR> And they won't die for a long time yet. You might be able to IR> get rid of some by good trade-in offers, but even that won't IR> help. Would you trade an SE for a LC475 at half the price? IR> Sure? Many people will say yes, but some may think twice. Some IR> of those Macs - especially SE - are *much* more reliable than IR> the new ones. That's (one of the reasons) why they were so IR> expensive. I'm extremely skeptical about this claim. Could you provide some evidence to support this? The reason they were so expensive was because Apple had huge profit margins. YHS:QSI! +++++++++++++++++++++++++++ >From isis@netcom.com (Mike Cohen) Date: Sun, 27 Feb 1994 20:27:17 GMT Organization: ISIS International cabu1hj@ube.ub.umd.edu writes: >In article , ingemar@lysator.liu.se >(Ingemar Ragnemalm) writes: >> >> [stuff deleted] >> >> That means killing off all Macs below LC III. Plus, SE, LC, LC II, Classic, >> Classic II, Color Classic, PB100,Portable, perhaps even IIcx, IIsi and IIvi. >> All those Macs are significantly nicer with System 6. >I think you need to double check statements like this. Several of these >systems run just fine with System 7.0, 7.0.1, & 7.1. Not with the >factory shipped memory (like 3MB on the IIsi). Running them with >8MB+ isn't unrealistic given the size of current applications either. I have a PB100, IIsi (with 14 megs of RAM & a FPU) and an SE/30 (acting as a file server). All of them run System 7 or later (S7Pro on the IIsi) and I don't think I could live with anything less. System 6 should finally be laid to rest. The speed & size difference isn't that great (the lean system on my PB even though I have CPU, FaxPro, & ARA is only 1300K) and the many benefits & convenience features of System 7 far outweigh the tiny speed difference. -- Mike Cohen - isis@netcom.com NewtonMail: MikeC49506 / ALink: D6734 / AOL: MikeC20 +++++++++++++++++++++++++++ >From L.H.Wood@lut.ac.uk Date: Sun, 27 Feb 1994 22:56:15 GMT Organization: Loughborough University, UK. In article <762314409.AA03366@nu91.wlink.nl> qsi@NU91.wlink.nl (Peter Kocourek) writes: >Ingemar Ragnemalm wrote in a message on 25 Feb 94 > > IR> That means killing off all Macs below LC III. Plus, SE, LC, > IR> LC II, Classic, Classic II, Color Classic, PB100,Portable, > IR> perhaps even IIcx, IIsi and IIvi. All those Macs are significantly > IR> nicer with System 6. Apple has designed System 7 in a way that > >I beg to differ. I have a IIsi here, and I don't see how running System 6 on it >would make it "nicer". I'd lose aliases, drag & drop, AppleEvents (and hence >AppleScript), a much better Finder, WorldScript, and Publish & Subscribe. How >can the loss of these make the machine "nicer"? > System 6 and 7 store things at the opposite ends of memory to each other. Under S6 on a IIsi, a large disk cache is not required to boost drawing-to video speeds. Nothing gets put in the remaining part of that megabyte until you fill the machine right up. Considering that the disk cache in not used under S6 Multifinder, this is a blessing twice over. (Aside: I've read that Apple are redoing the disk-cache code. Can we expect a disk cache whose size you don't set, that utilises free memory wherever it can, a la Windows NT, for System 7.5?) L. +++++++++++++++++++++++++++ >From neeri@iis.ee.ethz.ch (Matthias Neeracher) Date: 28 Feb 94 17:26:34 Organization: Integrated Systems Laboratory, ETH, Zurich In article , ingemar@lysator.liu.se (Ingemar Ragnemalm) writes: > time@garnet.msen.com (Tim Endres) writes: >>Bill Stewart-Cole (bsc@oui.com) wrote: >>: The whole discussion on supporting system 6 has spurred some thoughts: >>: Would not Mac developers benefit by a 100% move to system 7? >>: Would not Mac users benefit by upgrading to 7 and Macs that can run it well? > That means killing off all Macs below LC III. Plus, SE, LC, LC II, Classic, > Classic II, Color Classic, PB100,Portable, perhaps even IIcx, IIsi and IIvi. > All those Macs are significantly nicer with System 6. I do most of my programming on an original Mac II. For about a year, I had one System 6 and one System 7 startup volume, but it turned out taht I never used the System 6 volume anymore. Matthias - --- Matthias Neeracher neeri@iis.ee.ethz.ch "I feel morally and intellectually obligated simply to concede that the death penalty experiment has failed." -- Supreme Court Justice Harry A. Blackmun +++++++++++++++++++++++++++ >From wbostow@hounix.org (Wayne Bostow) Date: Mon, 28 Feb 1994 21:39:45 GMT Organization: Houston UNIX Users Group (HOUNIX), Houston, TX >If that were true, they would still hold a high value. I would think that profit margins, R&D, and inflation make up 99% of the reason. I think the used price lists show SE30s higher that Classic IIs and IIcx's higher than their LC replacements. I attribute it to people who want to continue using 6. There are lots of us not ready to spend thousands on hardware and software upgrades even to get something " *infinitely* nicer". -- __________________________________________________________ Wayne Bostow "The HangulMan" 10558 Alcott, Houston, TX 77043 ph. (713)468-6546 wbostow@hounix.org +++++++++++++++++++++++++++ >From gdl@stlawrence.maths (Mr_G._Landweber_student_tel_2-73550) Date: 28 Feb 1994 23:48:12 GMT Organization: (none) In article ingemar@lysator.liu.se (Ingemar Ragnemalm) writes: > Some of those Macs - especially SE - are *much* more > reliable than the new ones. That's (one of the reasons) why they were > so expensive. I remember writing a 3-page essay with WriteNow on my old Mac SE, and it crashed at least three times. More recently, I wrote a 50+ page thesis with Word and it only crashed once. In my experience, my Mac IIcx/Rocket is much more stable than my SE ever was. In fact, most of my crashes come from bugs in pre-release versions of Greg's Buttons (some pretty spectatular things happen when you patch _GetResource and trash A1). -- Greg "Buttons" Landweber gdl@maths.ox.ac.uk +++++++++++++++++++++++++++ >From cabu1hj@ube.ub.umd.edu Date: 28 Feb 94 19:53:09 -0500 Organization: University of Baltimore In article , WISEKB@caedm.et.byu.edu (Kevin B. Wise) writes: > > Long live system 6!!!!!!!!! Spoken like a ture horse & buggy man. +++++++++++++++++++++++++++ >From jwbaxter@olympus.net (John W. Baxter) Date: Tue, 01 Mar 1994 08:48:30 -0800 Organization: Internet for the Olympic Peninsula I don't want to prevent anyone from using System 6 who wants to do so. On the other hand, I haven't written anything for System 6 for a couple of years. I've forgotten how. I don't want to relearn. So...what I write won't do any good for people who run System 6. [But...I haven't released anything major recently, anyhow.] For some developers, there's still a nice market of System 6 users. Go for it! -- John Baxter Port Ludlow, WA, USA [West shore, Puget Sound] jwbaxter@pt.olympus.net +++++++++++++++++++++++++++ >From d88-jwa@mumrik.nada.kth.se (Jon Wätte) Date: 1 Mar 1994 19:42:48 GMT Organization: Royal Institute of Technology, Stockholm, Sweden In <1994Feb28.213945.20363@hounix.org> wbostow@hounix.org (Wayne Bostow) writes: > I think the used price lists show SE30s higher that Classic IIs and >IIcx's higher than their LC replacements. I attribute it to people who >want to continue using 6. I attribute it to an informed market; the SE30 is twice the speed of the Classic II and can take more memory; the IIcx is not only twice the speed of the LC, it also has three NuBus slots. Cheers, / h+ -- -- Jon W{tte, h+@nada.kth.se, Mac Hacker Deluxe -- "Don't use the Layer Manager" +++++++++++++++++++++++++++ >From temple@itd.nrl.navy.mil (Dr. Jon Gerard Temple) Date: Wed, 2 Mar 1994 20:11:17 GMT Organization: Naval Research Laboratory In article <2l05ro$mqi@news.kth.se> d88-jwa@mumrik.nada.kth.se (Jon Wätte) writes: > In <1994Feb28.213945.20363@hounix.org> wbostow@hounix.org (Wayne Bostow) writes: > > > I think the used price lists show SE30s higher that Classic IIs and > >IIcx's higher than their LC replacements. I attribute it to people who > >want to continue using 6. > > I attribute it to an informed market; the SE30 is twice the speed > of the Classic II and can take more memory; the IIcx is not only twice > the speed of the LC, it also has three NuBus slots. > Agreed. Moreover, the SE/30 and IIcx were quality machines. Designed well and made to last. The LCs and Classic IIs always feel cheap in comparison, with much less care taken in their design and manufacture. Not that I would turn my nose up at a LC475 (Q605)... Jon +++++++++++++++++++++++++++ >From ingemar@lysator.liu.se (Ingemar Ragnemalm) Date: Wed, 2 Mar 1994 19:29:08 GMT Organization: (none) cabu1hj@ube.ub.umd.edu writes: >In article , ingemar@lysator.liu.se >(Ingemar Ragnemalm) writes: >> >> [stuff deleted] >> >> That means killing off all Macs below LC III. Plus, SE, LC, LC II, Classic, >> Classic II, Color Classic, PB100,Portable, perhaps even IIcx, IIsi and IIvi. >> All those Macs are significantly nicer with System 6. >I think you need to double check statements like this. Several of these >systems run just fine with System 7.0, 7.0.1, & 7.1. Not with the >factory shipped memory (like 3MB on the IIsi). Running them with >8MB+ isn't unrealistic given the size of current applications either. I didn't say it won't work - it will, at least with 4 megs. I said that those Macs are so slow that they are *noticeably* more sluggish (at least in the Finder) when using System 7, and therefore many users won't change. And as long as many users have a better life with the *old* system, it won't go away in a long time. I've tried Sys 7 on my SE. Never again. I use System 7 on my LC. I wish I didn't have to, but with sys 6 it can't print due to the sys 7-running IIfx that uses the same printer. When I switch the LC to sys 6 (I have both on it, on separate disks) it feels like if I had plugged in an accelerator board. Plusses, SE's and Classics are best used with sys 6, if at all possible (again, sharing a printer might make it impossible). Faster, more memory (max 4, you know). LC's only for the speed difference. At IIsi, it's getting fast enough to consider upgrading to 7, but it does slow down... About that printer problem... Anyone who knows a way to make a sys 6 Mac work with the new printer drivers? Will 6.0.8 fix it? (Dumping in the new drivers didn't.) -- - - Ingemar Ragnemalm, PhD Image processing, Mac shareware games E-mail address: ingemar@isy.liu.se or ingemar@lysator.liu.se +++++++++++++++++++++++++++ >From ingemar@lysator.liu.se (Ingemar Ragnemalm) Date: Wed, 2 Mar 1994 19:41:30 GMT Organization: (none) L.H.Wood@lut.ac.uk writes: >Aside: I've read that Apple are redoing the disk-cache >code. Can we expect a disk cache whose size you don't set, that utilises free >memory wherever it can, a la Windows NT, for System 7.5? That could be nice, but even more important: will Apple get it act together and fix the memory management overall? It seems like RamDoubler will fix most of it for now, but fixes like that should go into the OS. Memory protection would be nice too. (I suppose I won't get that from RamDoubler.) -- - - Ingemar Ragnemalm, PhD Image processing, Mac shareware games E-mail address: ingemar@isy.liu.se or ingemar@lysator.liu.se +++++++++++++++++++++++++++ >From watkeyeh@dunx1.ocs.drexel.edu (Edwin H. Watkeys III) Date: Thu, 3 Mar 1994 00:47:57 GMT Organization: Drexel University In article ingemar@lysator.liu.se (Ingemar Ragnemalm) writes: >[A lot of stuff deleted] There's no point in arguing -- the speed tradeoff is worth it to me. I'd sooner use a typewriter than System 6. > >About that printer problem... Anyone who knows a way to make a sys 6 Mac >work with the new printer drivers? Will 6.0.8 fix it? (Dumping in the >new drivers didn't.) > I thought this was the reason 6.0.8 came out in the first place (to make System 6 compatible with System 7.x printing drivers). Try it. Ed -- Ed Watkeys watkeyeh@dunx1.ocs.drexel.edu Drexel University Philosopher-Programmer EdWatkeys@distant.com Distant Software +++++++++++++++++++++++++++ >From Brad Koehn Date: 4 Mar 1994 01:17:08 GMT Organization: University of Wisconsin In article Ingemar Ragnemalm, ingemar@lysator.liu.se writes: >I didn't say it won't work - it will, at least with 4 megs. I said that >those Macs are so slow that they are *noticeably* more sluggish (at least >in the Finder) when using System 7, and therefore many users won't change. >And as long as many users have a better life with the *old* system, it >won't go away in a long time. > >I've tried Sys 7 on my SE. Never again. I use System 7 on my LC. I wish >I didn't have to, but with sys 6 it can't print due to the sys 7-running >IIfx that uses the same printer. When I switch the LC to sys 6 (I have both >on it, on separate disks) it feels like if I had plugged in an accelerator >board. > >Plusses, SE's and Classics are best used with sys 6, if at all possible >(again, sharing a printer might make it impossible). Faster, more memory >(max 4, you know). LC's only for the speed difference. At IIsi, it's >getting fast enough to consider upgrading to 7, but it does slow down... > >About that printer problem... Anyone who knows a way to make a sys 6 Mac >work with the new printer drivers? Will 6.0.8 fix it? (Dumping in the >new drivers didn't.) The printer problem is from using the System 7 LW Driver alongside the System 6 LW Driver. Just put the Sys6 driver on the Sys7 machine and the printer won't re-initialize every time you print from the other machine. Also, I agree that Sys7 is more sluggish than Sys6, but you have to take into effect things like aliases (so you don't have to navigate to every file) and AppleScript. System 7 lets the Finder do more, and if you take advantage of the extra goodies, you can be more productive. As someone (I believe it was Jon) pointed out, there are far more Sys7 Macs out there, and more and more software is Sys7 only. While there may be some people out there that stick with Sys6, their number is getting smaller every day. Also, Sys6 don't tend to buy lots of new software, which is understandable, but doesn't help the "Sys7 required" trend. _________________________________________________________________________ Brad Koehn Data Transformations, Inc. koehn@macc.wisc.edu +++++++++++++++++++++++++++ >From worley@el.wpafb.af.mil (Rick Worley) Date: Fri, 4 Mar 94 16:42:31 GMT Organization: WL/ELM > >About that printer problem... Anyone who knows a way to make a sys 6 Mac >work with the new printer drivers? Will 6.0.8 fix it? (Dumping in the >new drivers didn't.) > 6.0.8 is available from ftp.apple.com//dts/sys.soft 6.0.8 is compatible with System 7 laserwriter drivers But you should install LaserWriter 8.1.1 on all your macs, it works with both System 6 and 7. Rick Worley Tel: (513) 255-7665 WL/ELM BLDG 620 Fax: (513) 476-4807 2241 AVIONICS CIRCLE SUITE 25 worley@el.wpafb.af.mil WRIGHT-PATTERSON AFB OH 45433-7327 +++++++++++++++++++++++++++ >From wbostow@hounix.org (Wayne Bostow) Date: Sun, 06 Mar 1994 23:02:22 GMT Organization: Houston UNIX Users Group (HOUNIX), Houston, TX >But you should install LaserWriter 8.1.1 on all your macs, it works with both System 6 and 7. Depends what you mean by "works". I heard this nonsense when sys 7 first came out and wasted a lot of time with it before taking it off to use with my LaserWriterPlus. Thing is, with that printer, there is a max of about 128k free for fonts using the sys 6 driver. Eat that away with the newer drivers and you cannot print your existing documents. If you are working alone and are printing OK now, don't change. -- __________________________________________________________ Wayne Bostow "The HangulMan" 10558 Alcott, Houston, TX 77043 ph. (713)468-6546 wbostow@hounix.org --------------------------- >From pope@imv.aau.dk (Povl H. Pedersen) Subject: Never beep when using GWorlds. System software bug! Date: 6 Mar 1994 12:52:05 GMT Organization: Information and Media Science, Aarhus University, DENMARK I just had to help a guy who used my PICT file saving code. He had some problems, and had inserted a SysBeep() in the bottleneck procedure to write the bytes. Now, the way my routine works is to create a new GWorld, SetGWorld, OpenPicture, CopyBits, ClosePicture. The problem is, that the machine he uses has the volume set to 0. When my GWorld is set, and the SysBeep() tries to flash the menubar, then the machine crashes each and every time! When I replaced the the SetGWorld with a SetPort to the port of the FronWindow(), then I got the flashing menu bar. Setting the sound volume > 0 gave me the beeps instead. So I would appreciate if some dude at Apple could look the code over, and make sure that FlashMenuBar() is only called with a valid GWorld, or sets/restores the window Gworld itself. Now, this problem will probably get low priority, as it affects <10% of the Maacintosh users (those with sound level set to 0). - - Povl H. Pedersen - Macintosh Consultant and Programmer System Administrator at the Aarhus Engineering School pope@imv.aau.dk (preferred) / povlphp@uts.uni-c.dk "Macintosh...for those who can see through Windows!" +++++++++++++++++++++++++++ >From tgreen@ersys.edmonton.ab.ca (Terry Greeniaus) Date: Thu, 10 Mar 94 15:46:30 MST Organization: Edmonton Remote Systems #1 pope@imv.aau.dk (Povl H. Pedersen) writes: > I just had to help a guy who used my PICT file saving code. > He had some problems, and had inserted a SysBeep() in the bottleneck > procedure to write the bytes. > > Now, the way my routine works is to create a new GWorld, SetGWorld, > OpenPicture, CopyBits, ClosePicture. > > The problem is, that the machine he uses has the volume set to 0. > When my GWorld is set, and the SysBeep() tries to flash the menubar, > then the machine crashes each and every time! When I replaced the > the SetGWorld with a SetPort to the port of the FronWindow(), then I > got the flashing menu bar. Setting the sound volume > 0 gave me the > beeps instead. > > So I would appreciate if some dude at Apple could look the code over, > and make sure that FlashMenuBar() is only called with a valid GWorld, > or sets/restores the window Gworld itself. > > Now, this problem will probably get low priority, as it affects <10% of > the Maacintosh users (those with sound level set to 0). > Well, I have also had problems with GWorlds, (offscreen ports, actually, but it's on a related topice.). If you are set to a port somewhere offscreen, and call SetWTitle() it will try to draw the window into your port off screen, and make funny things appear. (I'm not sure if the Inside Mac description says the set the port to the window who's title you're going to change, but that solved the problem.) "Yes, I have tricks in my pocket, I have things up my sleeve. But I am the opposite of a stage magician. He gives you illusion that has the appearance of truth. I give you truth in the pleasant disguise of illusion." --Tom Wingfield from "The Glass Menagerie" by T. Williams +++++++++++++++++++++++++++ >From markhanrek@aol.com (MarkHanrek) Date: 12 Mar 1994 04:37:00 -0500 Organization: America Online, Inc. (1-800-827-6364) I could be wrong, but I believe your problems has to do with the graphic device involved. It is a common "programming error" to not restore the graphic device along with the GWorld when working with GWorlds. This often happens when mixing the use of GetPort/SetPort and GetGWorld/SetGWorld calls. The guy who was having the problems using sysbeep was doing something incorrect, and it doesn't seem it is the system's responsibility to protect against a "programming error". The call to SysBeep should have been bracketed with the appropriate Get/SetGWorld calls to save and restore the port AND the graphic device. Actually, the System crashed because the graphic device for the monitor the menubar is on was not the currently active graphic device, I suspect. If Apple fixed SysBeep to be self protecting, then a jillion other routines would deserve upgrade. So you can see the problem. It sounds like I am saying it is your friend's fault, :) but actually it is the fault of less-than-adequate information management and accessibility here in the future. We developers have to know too much, and have yet to really use our computers to help alleviate this burden in a coordinated way. Hope this helps. Mark Hanrek The Information Workshop +++++++++++++++++++++++++++ >From rmah@panix.com (Robert S. Mah) Date: Sat, 12 Mar 1994 10:13:04 -0500 Organization: One Step Beyond markhanrek@aol.com (MarkHanrek) wrote: > [...] > The call to SysBeep should have been bracketed with the appropriate > Get/SetGWorld calls to save and restore the port AND the graphic device. >[...] I have to disagree. If SysBeep() normally affected the screen then, yes, it should be the application programmers responsibility to set/restore the GWorld, but the menu bar flashing behaviour is a special case inside SysBeep() and not part of it's "standard" behaviour. Thus, it is SysBeep that should be setting/restoring the GWorld. Of course, given the existance of this bug, the point is mute as the app programmer _must_ set/restore the GWorld when calling SysBeep() in order to have his stuff work. C'est la vie. Cheers, Rob ________________________________________________________________________ Robert S. Mah One Step Beyond rmah@panix.com +++++++++++++++++++++++++++ >From tgreen@ersys.edmonton.ab.ca (Terry Greeniaus) Date: Sun, 13 Mar 94 15:42:40 MST Organization: Edmonton Remote Systems #2 rmah@panix.com (Robert S. Mah) writes: > markhanrek@aol.com (MarkHanrek) wrote: > > > [...] > > The call to SysBeep should have been bracketed with the appropriate > > Get/SetGWorld calls to save and restore the port AND the graphic device. > >[...] > > I have to disagree. If SysBeep() normally affected the screen then, yes, > it should be the application programmers responsibility to set/restore > the GWorld, but the menu bar flashing behaviour is a special case inside > SysBeep() and not part of it's "standard" behaviour. Thus, it is SysBeep > that should be setting/restoring the GWorld. > > Of course, given the existance of this bug, the point is mute as the app > programmer _must_ set/restore the GWorld when calling SysBeep() in order > to have his stuff work. C'est la vie. > > Cheers, > Rob Well, if you're worried, at the start of your application, you could check the sound level and see if it was zero. Then set a Boolean variable to true if it is non-zero or false if it is zero. Then you could write some routine: void MySysBeep() { if (beepFlag) SysBeep(1); else { // Either save the current GWorld or not beep at all // SysBeep(); // Reset the current GWorld } } and then replace all your calls to SysBeep(1) with MySysBeep(); . There ya go! :-) "Yes, I have tricks in my pocket, I have things up my sleeve. But I am the opposite of a stage magician. He gives you illusion that has the appearance of truth. I give you truth in the pleasant disguise of illusion." --Tom Wingfield from "The Glass Menagerie" by T. Williams +++++++++++++++++++++++++++ >From Ralph Martin Date: Mon, 14 Mar 1994 16:22:13 +0000 Organization: University of Wales College of Cardiff In article Terry Greeniaus, tgreen@ersys.edmonton.ab.ca writes: >Well, if you're worried, at the start of your application, you could >check the sound level and see if it was zero. Then set a Boolean >variable to true if it is non-zero or false if it is zero. Then you >could write some routine: >void MySysBeep() >{ > if (beepFlag) > SysBeep(1); > else > { > // Either save the current GWorld or not beep at all > // SysBeep(); > // Reset the current GWorld > } >} >and then replace all your calls to SysBeep(1) with MySysBeep(); . And then when the user changes the sound level AFTER your program has started? Kaboom... +++++++++++++++++++++++++++ >From jwbaxter@olympus.net (John W. Baxter) Date: Mon, 14 Mar 1994 09:06:57 -0800 Organization: Internet for the Olympic Peninsula In article , tgreen@ersys.edmonton.ab.ca (Terry Greeniaus) wrote: Discussion of the need to save/restore GWorlds before SysBeep () omitted > > Well, if you're worried, at the start of your application, you could > check the sound level and see if it was zero. Then set a Boolean > variable to true if it is non-zero or false if it is zero. Then you > could write some routine: [omitted] Not at the start of the application: the user can change the sound level any time your app calls WaitNextEvent (). YOU wouldn't do that...but the whole point of the exercise is to make your code work on other people's machines. -- John Baxter Port Ludlow, WA, USA [West shore, Puget Sound] jwbaxter@pt.olympus.net +++++++++++++++++++++++++++ >From jim_reekes@quickmail.apple.com (Jim Reekes) Date: Tue, 15 Mar 1994 06:29:45 GMT Organization: Apple Computer, Inc. In article , rmah@panix.com (Robert S. Mah) wrote: > > markhanrek@aol.com (MarkHanrek) wrote: > > > [...] > > The call to SysBeep should have been bracketed with the appropriate > > Get/SetGWorld calls to save and restore the port AND the graphic device. > >[...] > > I have to disagree. If SysBeep() normally affected the screen then, yes, > it should be the application programmers responsibility to set/restore > the GWorld, but the menu bar flashing behaviour is a special case inside > SysBeep() and not part of it's "standard" behaviour. Thus, it is SysBeep > that should be setting/restoring the GWorld. > > Of course, given the existance of this bug, the point is mute as the app > programmer _must_ set/restore the GWorld when calling SysBeep() in order > to have his stuff work. C'est la vie. Well, I wrote SysBeep and I simply use the following code. FlashMenuBar(0); // just flash entire menu bar Delay(kMenuBarDelayTime, &finalTick); FlashMenuBar(0); If anyone is NOT saving/restoring the GWorlds, it could be the Menu Manager. I missed the original message, but this is not a sound manager bug. - --------------------------------------------------------------------- Jim Reekes, Polterzeitgeist | Macintosh Toolbox Engineering | Sound Manager Expert Apple Computer, Inc. | "All opinions expressed are mine, and do 20525 Mariani Ave. MS 302-3KS | not necessarily represent those of my Cupertino, CA 95014 | employer, Apple Computer Inc." +++++++++++++++++++++++++++ >From qsi@cnh.wlink.nl (Peter Kocourek) Date: Tue, 15 Mar 1994 00:04:37 +0100 Organization: (none) Terry Greeniaus wrote: TG> Well, if you're worried, at the start of your application, TG> you could check the sound level and see if it was zero. Then TG> set a Boolean variable to true if it is non-zero or false if TG> it is zero. Then you could write some routine: No, you should check the sound level every time just before the SysBeep, because users can and do change the sound level while your app is running. YHS:QSI! +++++++++++++++++++++++++++ >From KLUEV@jonathan.srcc.msu.su Date: Wed, 16 Mar 1994 21:02:49 +0300 Organization: (none) In article <763696813.AA01334@cnh.wlink.nl> qsi@cnh.wlink.nl (Peter Kocourek) writes: >Terry Greeniaus wrote: > > TG> Well, if you're worried, at the start of your application, > TG> you could check the sound level and see if it was zero. Then > TG> set a Boolean variable to true if it is non-zero or false if > TG> it is zero. Then you could write some routine: > >No, you should check the sound level every time just before the SysBeep, >because users can and do change the sound level while your app is running. (SoundLevel <> 0) doesn't lead to (There will be sound, and not flash). Michael Kluev. --------------------------- >From ViviStar@ACM.org (Jonathan Hess) Subject: PPC & 68k UPP problems Date: Tue, 1 Mar 1994 00:56:35 GMT Organization: ViviStar Consulting I've reviewed "Making the Leap to PowerPC" article in develop 16 but find its description of Universal ProcPtrs lacking. Particularly in relation to coding source that is compatible with both 68k and PowerPC systems. Using the code snippets from that article would lead one to believe that a global declaration of: RoutineDescriptor gVActionProcRD = BUILD_ROUTINE_DESCRIPTOR( uppControlActionProcInfo, VActionProc); with code such as: TrackControl(ctlHit, mouseLoc, (ControlActionUPP) &gVActionProcRD); would work under both PowerPC and 68k systems. While this might work with PowerPC systems it clearly will not work with 68k systems -- VActionProc should be passed in the TrackControl call but taking the address of gVActionProcRD can not possibly return that appropriate address. Anyone have some sample code you could link me or that I could ftp from somewhere? Thanks, Jonathan Hess ViviStar Consulting +++++++++++++++++++++++++++ >From zstern@adobe.com (Zalman Stern) Date: Tue, 1 Mar 1994 12:25:29 GMT Organization: Adobe Systems Incorporated Jonathan Hess writes > I've reviewed "Making the Leap to PowerPC" article in develop 16 but > find its description of Universal ProcPtrs lacking. Particularly in > relation to coding source that is compatible with both 68k and PowerPC > systems. > > Using the code snippets from that article would lead one to believe > that a global declaration of: > > RoutineDescriptor gVActionProcRD = BUILD_ROUTINE_DESCRIPTOR( > uppControlActionProcInfo, VActionProc); > > with code such as: > > TrackControl(ctlHit, mouseLoc, (ControlActionUPP) &gVActionProcRD); > > would work under both PowerPC and 68k systems. While this might work > with PowerPC systems it clearly will not work with 68k systems -- > VActionProc should be passed in the TrackControl call but taking the > address of gVActionProcRD can not possibly return that appropriate > address. > > Anyone have some sample code you could link me or that I could ftp from > somewhere? I'd do something like this. In a header file have the following: #if NEEDROUTINEDESCRIPTORS #define MakeStaticRoutineDesc(name, procinfo) \ RoutineDescriptor name##RDS = \ BUILD_ROUTINE_DESCRIPTOR(procinfo, name); #else #define MakeStaticRoutineDesc(name, procinfo) #endif #if NEEDROUTINEDESCRIPTORS #define ExternRoutineDescriptor(name) \ extern RoutineDescriptor name##RDS; #else #define ExternRoutineDesc(name) #ednif #if NEEDROUTINEDESCRIPTORS #define ConditionalRD(name) (&name##RDS) #else #define ConditionalRD(name) (&name) #endif To use this write code like so: pascal void VActionProc(ControlHandle theControl, short partCode) { /* ... */ } MakeStaticRoutineDesc(VActionProc, uppControlActionProcInfo) { TrackControl(ctlHit, mouseLoc, (ControlActionUPP) ConditionalRD(VActionProc)); } The ExternRoutineDesc macro is used in addition to existing extern prototypes in header files. (Ideally, the Apple header files would declare a direct function type for each callback in addition to the function pointer type, but they don't. If they did, ExternRoutineDesc could declare either a function or a RoutineDescriptor structure.) -- Zalman Stern zalman@adobe.com (415) 962 3824 Adobe Systems, 1585 Charleston Rd., POB 7900, Mountain View, CA 94039-7900 "Do right, and risk consequences." Motto of Sam Houston (via Molly Ivins) +++++++++++++++++++++++++++ >From d88-jwa@mumrik.nada.kth.se (Jon Wätte) Date: 1 Mar 1994 19:50:23 GMT Organization: Royal Institute of Technology, Stockholm, Sweden In ViviStar@ACM.org (Jonathan Hess) writes: >Using the code snippets from that article would lead one to believe >that a global declaration of: > RoutineDescriptor gVActionProcRD = BUILD_ROUTINE_DESCRIPTOR( > uppControlActionProcInfo, VActionProc); >would work under both PowerPC and 68k systems. While this might work >with PowerPC systems it clearly will not work with 68k systems -- >VActionProc should be passed in the TrackControl call but taking the >address of gVActionProcRD can not possibly return that appropriate >address. No, but it might be that under the 68k environment, the routine descriptor includes a JMP instruction and the address... However, that doesn't appear to be the case; instead, you're supposed to call NewControlActionProc which WILL work on both kinds of systems. Cheers, / h+ -- -- Jon W{tte, h+@nada.kth.se, Mac Hacker Deluxe -- "Don't use the Layer Manager" +++++++++++++++++++++++++++ >From t-gaul@i-link.com (Troy Gaul) Date: Wed, 02 Mar 1994 15:29:32 -0600 Organization: I-Link, Ltd. In article <2l069v$mt4@news.kth.se>, d88-jwa@mumrik.nada.kth.se (Jon Wtte) wrote: > In ViviStar@ACM.org (Jonathan Hess) writes: > > >Using the code snippets from that article would lead one to believe > >that a global declaration of: > > > RoutineDescriptor gVActionProcRD = BUILD_ROUTINE_DESCRIPTOR( > > uppControlActionProcInfo, VActionProc); > > >would work under both PowerPC and 68k systems. While this might work > >with PowerPC systems it clearly will not work with 68k systems -- > >VActionProc should be passed in the TrackControl call but taking the > >address of gVActionProcRD can not possibly return that appropriate > >address. > > No, but it might be that under the 68k environment, the routine > descriptor includes a JMP instruction and the address... > > However, that doesn't appear to be the case; instead, you're > supposed to call NewControlActionProc which WILL work on both > kinds of systems. Yeah, but that creates it in the heap (on PowerPC), not on the stack, which can be advantageous at times. Zalman Stern recently posted a technique in this thread that allows you to create a static routine descriptor, which it looked like, would also work for stack-based RDs. This can be useful for things like DeviceLoop drawing procs that don't have to stay around for long to avoid creating and disposing in the heap all of the time (in code like a WDEF that, on the 68K, can't have global data -- I know that it can on the PowerPC, but I wanted to do it in a portable way for if/when RDs are supported on 68K). _troy //////// //////___Troy Gaul_________________________t-gaul@i-link.com__ // // // I-Link, Ltd. ; West Des Moines, Iowa // // // // "Iungo ergo sum." (I-Link, therefore I am.) // // //////________________________________________________________ // --------------------------- >From arose@ATHENA.MIT.EDU (Alex Rosen) Subject: PPC binaries Date: 7 Mar 1994 17:05:23 GMT Organization: Massachusetts Institute of Technology (1) Since PPC code is in the data fork and 68k code is in the resource fork: Would it be possible to embed a tiny 68k app in my PPC app, which just pops up a dialog saying "This program is for PPC computers, please install the 68k version" or something like that? (2) I assume that CodeWarrior and the Apple SDK don't use any of the instructions on the 601 that aren't part of the PPC spec, and that may not be around on future chips. Is this so? Might these instructions be emulated via traps on future chips? (3) Has Apple said anything about low memory globals on PPC? If Apple were to release a system with memory protection, it would seem that all apps which access LMGs directly would break, and there are plenty of these apps around. But it seems that recompiling for PPC is the perfect time for developers to replace this code with system software calls (e.g. GetMBarHeight(), SetMBarHeight() ). Any word from Apple on this? --Alex +++++++++++++++++++++++++++ >From d88-jwa@mumrik.nada.kth.se (Jon Wätte) Date: 7 Mar 1994 19:13:25 GMT Organization: Royal Institute of Technology, Stockholm, Sweden In <2lfmsj$otv@senator-bedfellow.MIT.EDU> arose@ATHENA.MIT.EDU (Alex Rosen) writes: >(1) Since PPC code is in the data fork and 68k code is in the resource >fork: Would it be possible to embed a tiny 68k app in my PPC app, >which just pops up a dialog saying "This program is for PPC computers, >please install the 68k version" or something like that? It's not only possible, it's THE LAW, unless you shiip a fat binary. Now, should you embed a tiny PEF that says "this application is only for 68k Macs" ? :-) There is sample code on the SDK to show this, though it's really as trivial as building: void main ( void ) { InitGraf ( & qd . thePort ) ; InitFonts ( ) ; InitWindows ( ) ; InitMenus ( ) ; TEInit ( ) ; InitDialogs ( ) ; Alert ( 666 , NULL ) ; } and pasting your app resources into the native (nee, "optimized") app. >(2) I assume that CodeWarrior and the Apple SDK don't use any of the >instructions on the 601 that aren't part of the PPC spec, and that may >not be around on future chips. Is this so? Might these instructions be >emulated via traps on future chips? They're all clean. >(3) Has Apple said anything about low memory globals on PPC? If Apple Yeah, they're still there (if you call LMGetCurDeactive() or LMSetXXX) However, in the future, the programming model might rid itself of lo-mem globals. -- -- Jon W{tte, h+@nada.kth.se, Mac Hacker Deluxe -- There's no problem that can't be solved using brute-force algorithms and a sufficiently fast computer. Ergo, buy more hardware. (NOT!) +++++++++++++++++++++++++++ >From gdl@stlawrence.maths (Mr_G._Landweber_student_tel_2-73550) Date: 07 Mar 1994 23:38:36 GMT Organization: (none) In article <2lfmsj$otv@senator-bedfellow.MIT.EDU> arose@ATHENA.MIT.EDU (Alex Rosen) writes: (3) Has Apple said anything about low memory globals on PPC? If Apple were to release a system with memory protection, it would seem that all apps which access LMGs directly would break, and there are plenty of these apps around. But it seems that recompiling for PPC is the perfect time for developers to replace this code with system software calls (e.g. GetMBarHeight(), SetMBarHeight() ). Any word from Apple on this? As of the first PowerMacs, all the low memory globals--both documented and not--are still there. However, the universal header files for compling PowerPC native (and 680x0) apps no longer define these globals. They use "Get..." and "Set..." macros instead. -- Greg "Buttons" Landweber gdl@maths.ox.ac.uk +++++++++++++++++++++++++++ >From DACRXL01.OURX124@tcp30.dx.deere.com (Juan Ingles) Date: Tue, 8 Mar 1994 18:16:12 GMT Organization: Proteus Ventures, Inc. In article <2lfucm$21c@news.kth.se> d88-jwa@mumrik.nada.kth.se (Jon Wätte) writes: > void > main ( void ) { > InitGraf ( & qd . thePort ) ; > InitFonts ( ) ; > InitWindows ( ) ; > InitMenus ( ) ; > TEInit ( ) ; > InitDialogs ( ) ; > Alert ( 666 , NULL ) ; > } InitDialogs ( ) should be: InitDialogs ( NULL ) Tsk... Tsk... Jon, you forgot your resumeProc Ptr. :) >-- > -- Jon W{tte, h+@nada.kth.se, Mac Hacker Deluxe -- >There's no problem that can't be solved using brute-force algorithms >and a sufficiently fast computer. Ergo, buy more hardware. (NOT!) There's no code that can't be optimized. Ergo, spend the rest of your life optimizing code, and in the end the code won't take any time to run at all. ;) Juan Ingles -- Proteus Ventures, Inc. - Computer Software Consulting and Development 1514 Oriole Ave * Waterloo, IA 50701 * (319) 232-0985 +++++++++++++++++++++++++++ >From ejf0@ns1.cc.lehigh.edu (EUGENE JOSEPH FOSS) Date: Thu, 10 Mar 1994 03:34:55 GMT Organization: Lehigh University Jon Wätte (d88-jwa@mumrik.nada.kth.se) wrote: : Now, should you embed a tiny PEF that says "this application is only : for 68k Macs" ? :-) Well, you could if you wanted too, but wouldn't it be a little silly? I mean, since all the PPC Macs include 68k emulation... -- Eugene Foss CS/Math/Cog. Sci. --------------------------------------------------------------------- "Eating meat on Fridays may not be a mortal sin anymore, but I bet there are still some guys in hell doing time on a meat rap." +++++++++++++++++++++++++++ >From d88-jwa@mumrik.nada.kth.se (Jon Wätte) Date: 10 Mar 1994 10:30:50 GMT Organization: Royal Institute of Technology, Stockholm, Sweden >: Now, should you embed a tiny PEF that says "this application is only >: for 68k Macs" ? :-) >Well, you could if you wanted too, but wouldn't it be a little silly? I mean, >since all the PPC Macs include 68k emulation... There WAS a smiley there after all. The more relevant reason being there may be a PPC version, and users should know they're losing out on performance. So, your installer could choose between installing 1) Full fat binary 2) PPC code with tiny 68k alert 3) 68k code with tiny PEF alert Cheers, / h+ -- -- Jon W{tte, h+@nada.kth.se, Mac Hacker Deluxe -- The word "politics" is derived from the word "poly", meaning "many", and the word "ticks", meaning "blood sucking parasites". -- Larry Hardiman +++++++++++++++++++++++++++ >From zstern@adobe.com (Zalman Stern) Date: Thu, 10 Mar 1994 18:59:10 GMT Organization: Adobe Systems Incorporated Jon W tte writes > > >: Now, should you embed a tiny PEF that says "this application is only > >: for 68k Macs" ? :-) > > >Well, you could if you wanted too, but wouldn't it be a little silly? I mean, > >since all the PPC Macs include 68k emulation... > > There WAS a smiley there after all. > > The more relevant reason being there may be a PPC version, and > users should know they're losing out on performance. > > So, your installer could choose between installing > 1) Full fat binary > 2) PPC code with tiny 68k alert > 3) 68k code with tiny PEF alert Its just as easy to gestalt for the PowerPC in your 68k code. However, there is an interesting question there about how one should differentiate between running PowerPC and 68K code. A good solution is to put something in the splash screen. (At least for apps with heavy weight splash screens.) Likewise, this would appear in the about box. The question is what should be there? -- Zalman Stern zalman@adobe.com (415) 962 3824 Adobe Systems, 1585 Charleston Rd., POB 7900, Mountain View, CA 94039-7900 "Do right, and risk consequences." Motto of Sam Houston (via Molly Ivins) --------------------------- >From gewekean@studentg.msu.edu (Andrew Geweke) Subject: Passing data through to completion procs? Date: Wed, 16 Mar 1994 22:06:40 -0500 Organization: Michigan State University What I'm doing is writing an interface library to MacTCP; I want it to be simple. All routines are async, so I just want to have the caller pass in a simple structure pointer; a field in the struct gets changed when the call completes. I want to do this rather than having the user ravage through large ParamBlocks and so forth for simplicity and so on. My question is this: How can I get the Device Manager to pass four bytes to a completion routine that I pass in when I make the call? Basically, I'm having trouble getting a pointer to the structure through to the completion routine. Is there any place I can stash this? I'm looking through the ParamBlock structure right now, and everything's used or "not used" (which, as we all know, means reserved -- I don't want to break rules here). Here are my ideas so far: (1) Set the user up with a pointer to the ioResult field. Disadvantage: I want to deallocate the parameter-block's memory as soon as the call completes. This would require the user to do this. (2) Create a linked list of all outstanding calls with pointers to their parameter blocks. This is a roundabout method, though it should work; however, I'd rather not. Basically, I'm converting async calls from the beasts that they are into simple ones; you pass in a struct with only the specific information that gets a flag set when it's done. Any ideas? +++++++++++++++++++++++++++ >From resnick@cogsci.uiuc.edu (Pete Resnick) Date: Thu, 17 Mar 1994 01:37:49 -0600 Organization: University of Illinois at Urbana-Champaign In article <9403162206.AA40375@geweke.ppp.msu.edu>, gewekean@studentg.msu.edu (Andrew Geweke) wrote: >What I'm doing is writing an interface library to MacTCP; > >My question is this: How can I get the Device Manager to pass four bytes to a >completion routine that I pass in when I make the call? > >Basically, I'm having trouble getting a pointer to the structure through to >the completion routine. Is there any place I can stash this? Since you're using MacTCP, you're in luck. Every MacTCP param block has a userDataPtr field, which is exactly where you can store any pointer you like. Even if this field weren't there, you can do the same thing. Just make your own personal parameter block which contains everything the real parameter block does, plus one pointer field tacked onto the end. The Device Manager and driver are only going to use the fields they specify, so this is perfectly safe. (How could it not be? It would be quite ugly if a device driver decided to use some memory past the end of its parameter block!) pr -- Pete Resnick (...so what is a mojo, and why would one be rising?) Graduate assistant - Philosophy Department, Gregory Hall, UIUC System manager - Cognitive Science Group, Beckman Institute, UIUC Internet: resnick@cogsci.uiuc.edu +++++++++++++++++++++++++++ >From zben@ni.umd.edu (Charles B. Cranston) Date: 18 Mar 1994 00:50:47 GMT Organization: UMCP Network Infrastructures In article <9403162206.AA40375@geweke.ppp.msu.edu>, gewekean@studentg.msu.edu (Andrew Geweke) wrote: > What I'm doing is writing an interface library to MacTCP; I want it to be > simple. All routines are async, so I just want to have the caller pass in a > simple structure pointer; a field in the struct gets changed when the call > completes. I want to do this rather than having the user ravage through large > ParamBlocks and so forth for simplicity and so on. > My question is this: How can I get the Device Manager to pass four bytes to a > completion routine that I pass in when I make the call? Another approach would be to erect a "trampoline" somewhere. This would be 8 bytes consisting of a JSr to the real handler followed by the four data bytes. The real handler immediately does a Move.L (A7)+,A0 and then A0 points to the four data bytes, and the stacktop is now the real final return address. For MacTCP the UserData approach or the embed-IOPB-in-larger-known-block approaches would both work. I am thinking about using this trampoline technique for EtherNet "Protocol Handlers" where the IOPB is not passed to the callback routine. The cost, of course, is allocating and freeing the memory space for the trampoline, especially in the asynchronous environment you are talking about. --------------------------- >From Dmitry Boldyrev Subject: Password editing item.. Tricky? Date: 23 Feb 1994 02:22:25 GMT Organization: University of Utah Hi All. I am wounding if anyone has implemented so called scrambled editing item I looked at the ftp.apple.com and found a couple of codes which would do it but, I don't think it is the best way to do.. I am gonna use it for my FTP client. so, when I type my password "hello" it should actually print on the display "!!!!!". and the buffer should have "hello" so that I can then use it. I am thinking that there should be a way of writing a small routine and hook the interruption and everything what supposed to be displayed will be taken care by that routine.. Any ideas how it can be implemented? (Pascal, C iz ok) Thank you very much! ...................................................................... . Dmitry Boldyrev . (_) (_) . . University of Utah, Salt Lake City . |---| urricane, inc . . Utah, USA . (_) (_) . . Home Tel: (801) 581-1298, Office Tel: (801) 581-5465 . ...................................................................... +++++++++++++++++++++++++++ >From infosafe@panix.com (Tom Lipscomb) Date: 22 Feb 1994 23:57:18 -0500 Organization: PANIX Public Access Internet and Unix, NYC The easiest solution I came up with was to make my own font, which had one character (a diamond) for all of the letters. Use this font for the edit text that they are typing the password in. Cheers, Bradford Smith +++++++++++++++++++++++++++ >From Jonathan D Baumgartner Date: 23 Feb 1994 15:11:37 GMT Organization: Computing & Information Services, University of New Hampshire In article <2kenne$rku@panix2.panix.com> Tom Lipscomb, infosafe@panix.com writes: >The easiest solution I came up with was to make my own font, which had >one character (a diamond) for all of the letters. Use this font for >the edit text that they are typing the password in. That's an interesting solution; wish I'd thought of that earlier :-) I did this by creating a dialog filter which I pass to ModalDialog. When a keyDown or autoKey event occurs, it takes the character, appends it to a dummy string, and then changes the EventRecord's message to a bullet. This way you end up with a string that holds the password, but the user only sees bullets on-screen. I found a really excellent example (but HUGE, and it does a lot of other stuff besides) in the source for John Norstad's NewsWatcher. jon -- Jonathan D. Baumgartner Jonathan.D.Baumgartner@unh.edu Computing & Information Services, University of New Hampshire "It's just a matter of opinion." -- Primus +++++++++++++++++++++++++++ >From Scott_Gruby@hmc.edu (Scott Gruby) Date: Wed, 23 Feb 1994 07:34:32 -0800 Organization: Harvey Mudd College, Claremont CA In article <2kfrn9$d4v@mozz.unh.edu>, Jonathan D Baumgartner wrote: > I did this by creating a dialog filter which I pass to ModalDialog. When > a keyDown or autoKey event occurs, it takes the character, appends it to > a dummy string, and then changes the EventRecord's message to a bullet. > This way you end up with a string that holds the password, but the user > only sees bullets on-screen. > > I found a really excellent example (but HUGE, and it does a lot of other > stuff besides) in the source for John Norstad's NewsWatcher. > There's a snippet on ftp.apple.com that shows 3 ways of doing this; 1 is with a different font, 1 is as you described and I forgot what the 3rd one was. Anyway there is an example that is really SMALL and very easy to understand. -- Scott Allen Gruby (Scott_Gruby@hmc.edu) Macintosh Student System Manager Academic Computing, Harvey Mudd College Claremont, CA 91711 +++++++++++++++++++++++++++ >From mwalker@netcom.com (Mel Walker) Date: Wed, 23 Feb 1994 17:01:30 GMT Organization: Committee to Elect Dan Quayle Lord of the Cosmos Dmitry Boldyrev (dmitry@atlas.chem.utah.edu) wrote: : Hi All. : I am wounding if anyone has implemented so called scrambled editing item : I looked at the ftp.apple.com and found a couple of codes which would do : it : but, I don't think it is the best way to do.. : I am gonna use it for my FTP client. so, when I type my password "hello" : it should actually print on the display "!!!!!". and the buffer should : have "hello" so that I can then use it. : I am thinking that there should be a way of writing a small routine and : hook the interruption and everything what supposed to be displayed will : be taken care by that routine.. : Any ideas how it can be implemented? (Pascal, C iz ok) : Thank you very much! My prefered way is to have two text boxes for the password, one of which is outside of the dialog (i.e., it's invisible). Use a filter routine in your modal dialog that puts keystrokes into the invisible field, and puts a ! into the visible field. Backspaces, selections, and the like affect both fields. I may be explaining this badly. Send me email if you want more help. -- Mel Walker mwalker@netcom.com "Natural exuberance is one of those qualities that makes us tigers so darn endearing!" -- Hobbes +++++++++++++++++++++++++++ >From Dmitry Boldyrev Date: 23 Feb 1994 18:27:43 GMT Organization: University of Utah In article <2kfrn9$d4v@mozz.unh.edu> Jonathan D Baumgartner, Jonathan.D.Baumgartner@unh.edu writes: >That's an interesting solution; wish I'd thought of that earlier :-) > >I did this by creating a dialog filter which I pass to ModalDialog. When >a keyDown or autoKey event occurs, it takes the character, appends it to >a dummy string, and then changes the EventRecord's message to a bullet. >This way you end up with a string that holds the password, but the user >only sees bullets on-screen. > >I found a really excellent example (but HUGE, and it does a lot of other >stuff besides) in the source for John Norstad's NewsWatcher. Yeah, I know about the way of making such a font.. looks like it is the only solution I can think of. I've done the same way as Johnatan described, but there iz a little problem. Suppose you want to show a password when you create a window.. How would you do it? like I want !!!!!! to be shown when the dialog appears.. they way you suggest it it won't work. Thanks for the replies, guys! +++++++++++++++++++++++++++ >From Dmitry Boldyrev Date: 23 Feb 1994 18:28:57 GMT Organization: University of Utah In article <2kenne$rku@panix2.panix.com> Tom Lipscomb, infosafe@panix.com writes: >The easiest solution I came up with was to make my own font, which had >one character (a diamond) for all of the letters. Use this font for >the edit text that they are typing the password in. > >Cheers, >Bradford Smith A little problem too. How would you do it if you have two editing items? When you change the font, it will make all TE items the same font.. ? Thanks Dmitry. +++++++++++++++++++++++++++ >From hrafal@copernicus.bbn.com (Howie Rafal) Date: 23 Feb 1994 19:24:30 GMT Organization: BBN, Inc In article <2kenne$rku@panix2.panix.com>, infosafe@panix.com (Tom Lipscomb) wrote: > > The easiest solution I came up with was to make my own font, which had > one character (a diamond) for all of the letters. Use this font for > the edit text that they are typing the password in. > > Cheers, > Bradford Smith Be careful to not allow copy in the item, because it could be pasted somewhere else and the font changed. I use a TCL class called CPasswordText that I could forward to you if you want. It actually uses a bullet character and maintains a text item offscreen. I also have classes for password dialogs which handle turning on and off the OK button based on the login fields having values entered. HOWIE. +++++++++++++++++++++++++++ >From peter@ncrpda.curtin.edu.au (Peter N Lewis) Date: 24 Feb 1994 10:39:33 +0800 Organization: NCRPDA, Curtin University infosafe@panix.com (Tom Lipscomb) writes: >The easiest solution I came up with was to make my own font, which had >one character (a diamond) for all of the letters. Use this font for >the edit text that they are typing the password in. Don't spaces show up though? Last time I tried this, the spaces showed up even if your font didn't define the space character or even if you did, it would show up as a space. This was a long time back, maybe its changed? Peter. -- _______________________________________________________________________ Peter N Lewis Ph: +61 9 368 2055 +++++++++++++++++++++++++++ >From Jonathan D Baumgartner Date: 24 Feb 1994 18:24:47 GMT Organization: Computing & Information Services, University of New Hampshire In article <2kg76v$bei@u.cc.utah.edu> Dmitry Boldyrev, dmitry@atlas.chem.utah.edu writes: >Yeah, I know about the way of making such a font.. looks like it is the >only >solution I can think of. I've done the same way as Johnatan described, but >there iz a little problem. Suppose you want to show a password when you >create >a window.. How would you do it? >like I want !!!!!! to be shown when the dialog appears.. they way you >suggest >it it won't work. Um, you mean you want the password to show up as a series of !s before anything is typed? Like a default password or something? Assuming that's what you mean, I just use GetDItem() and SetIText(). Get a handle to the edit text field with GetDItem(), and then use SetIText() to change the text to an appropriate number of !s. (Appropriate number in this case would be the length of the actual password.) jon -- Jonathan D. Baumgartner Jonathan.D.Baumgartner@unh.edu Computing & Information Services, University of New Hampshire "It's just a matter of opinion." -- Primus +++++++++++++++++++++++++++ >From f8dy@access.netaxs.com (Mark Pilgrim) Date: 24 Feb 1994 22:22:38 GMT Organization: Net Access - Philadelphia's Internet Connection Peter N Lewis (peter@ncrpda.curtin.edu.au) wrote: : infosafe@panix.com (Tom Lipscomb) writes: : >The easiest solution I came up with was to make my own font, which had : >one character (a diamond) for all of the letters. Use this font for : >the edit text that they are typing the password in. : Don't spaces show up though? Last time I tried this, the spaces showed up : even if your font didn't define the space character or even if you did, : it would show up as a space. This was a long time back, maybe its changed? : Peter. Peter, you are correct. Tom, the one (potential) problem with your method is that one could copy the password to the clipboard and paste it somewhere else in a different font -- especially a problem if the dialog box is coming up with a password already there (in diamonds or bullets or bangs). After much agonizing over this issue, I finally went with the "editable text item outside the frame of the dialog" approach. I did _not_ have a second text item that mirrored the first one with bullets(/diamonds/bangs); instead, I displayed a character count (similar to Compact Pro) which updated with every keypress to the length of the editable text box. (This covers the situation of a user pasting in a password and/or cutting part of it out, where the length of the password may change by more than +-1.) And I had checkboxes to hide/show the character count and hide/show the password itself -- both of which should be saved a preferences and restored the next time the user has to enter a password. Of course, this doesn't solve the problem of having a password there when the dialog box comes up, since you could just check "show password" and see it. (: But having a password there is an inherent security weakness. I have discovered the password to an Appletalk server in the Chooser because the password was "there" but expressed in bullet characters (i.e. copying and pasting just yields bullets). Replacing one character at a time and seeing if it was still the right password gave me the password in less than a minute. (Of course, I assumed standard character frequencies and the password happened to be "tres", but it's still a bad assumption that just because the dialog box contains bullet characters that the underlying password is safe.) -- Mark Pilgrim | f8dy@netaxs.com | Please do not worry the philosophers. "I can't say enough about the importance of brevity." +++++++++++++++++++++++++++ >From ez015670@hamlet.ucdavis.edu () Date: Fri, 25 Feb 1994 00:33:49 GMT Organization: University of California, Davis Mark Pilgrim (f8dy@access.netaxs.com) wrote: : Peter N Lewis (peter@ncrpda.curtin.edu.au) wrote: : : Don't spaces show up though? Last time I tried this, the spaces showed up : : even if your font didn't define the space character or even if you did, : : it would show up as a space. This was a long time back, maybe its changed? : : Peter. : Peter, you are correct. Tom, the one (potential) problem with your method Another potential security problem that has not been addressed is the picking up of the password at a much lower level. I have made a program that prints all the characters pressed to a file including passwords. Maybe through a jGNE filter one could remove the characters before other inits can get a hold of them. Bret Olmsted olmsted@cs.ucdavis.edu +++++++++++++++++++++++++++ >From scott.m.silver@dartmouth.edu (Scott M. Silver) Date: 25 Feb 1994 03:28:06 GMT Organization: Dartmouth College - Hanover, NH In article ez015670@hamlet.ucdavis.edu () writes: > Another potential security problem that has not been addressed is the picking > up of the password at a much lower level. I have made a program that > prints all the characters pressed to a file including passwords. Maybe > through a jGNE filter one could remove the characters before other inits > can get a hold of them. This sort of seems to be one of those things where if "the person can get to the computer-locally, then your data is not safe". (Unless it's encrypted). Anyone can patch every single trap, write a jGNE filter, etc and figure out what your password is (or get a program to watch you type it in). Hell, they could video tape you typing it in. Scott ____________________________________________________________________ Scott Silver Dartmouth College Hanover, NH +++++++++++++++++++++++++++ >From d88-jwa@mumrik.nada.kth.se (Jon Wätte) Date: 24 Feb 1994 10:47:58 GMT Organization: Royal Institute of Technology, Stockholm, Sweden In <2kfrn9$d4v@mozz.unh.edu> Jonathan D Baumgartner writes: >>The easiest solution I came up with was to make my own font, which had >>one character (a diamond) for all of the letters. Use this font for >>the edit text that they are typing the password in. >That's an interesting solution; wish I'd thought of that earlier :-) Because fonts in applications are a bad idea (for a number of Font Manager reasons) What I do is I patch the QuickDraw text measurement and text drawing bottlenecks to measure a string of bullets instead of the real string. Cheers, / h+ -- -- Jon W{tte, h+@nada.kth.se, Mac Hacker Deluxe -- Not speaking for the Microsoft Corporation. +++++++++++++++++++++++++++ >From infosafe@panix.com (Tom Lipscomb) Date: 25 Feb 1994 01:11:10 -0500 Organization: PANIX Public Access Internet and Unix, NYC In article <2kg799$bei@u.cc.utah.edu>, Dmitry Boldyrev wrote: >In article <2kenne$rku@panix2.panix.com> Tom Lipscomb, infosafe@panix.com >writes: >>The easiest solution I came up with was to make my own font, which had >>one character (a diamond) for all of the letters. Use this font for >>the edit text that they are typing the password in. >> >>Cheers, >>Bradford Smith > >A little problem too. >How would you do it if you have two editing items? >When you change the font, it will make all TE items the same font.. ? >Thanks > >Dmitry. For static text I made them User Items that drew the appropriate text in Chicago. For the field where they typed the name, I set the font to be Geneva, or something. For the field where I put the password, I set the font to be .pwd font (or whatever it was). It's not the most secure method; as lots of people pointed out, you can copy it to another field and see what the text is. For me this was not a concern, though. The person typed in the name and pwd, it was accepted or rejected, and they moved on. The only person who could have copied the text to another app was the person who just typed it in -- not a security risk. As for writing an init to catch the keystrokes -- anyone know how to stop it? Cheers, Bradford +++++++++++++++++++++++++++ >From Jim.Matthews@dartmouth.edu (Jim Matthews) Date: 25 Feb 1994 14:11:52 GMT Organization: Dartmouth College In article <2ki0ku$pir@news.kth.se>, d88-jwa@mumrik.nada.kth.se (Jon Wtte) wrote: > What I do is I patch the QuickDraw text measurement and text > drawing bottlenecks to measure a string of bullets instead of > the real string. I tried that once but found it difficult to tell when StdText and StdMeas were being called for the password, as opposed to anything else in the dialog. Is there a sure-fire way to do this? Jim Matthews Dartmouth Software Development +++++++++++++++++++++++++++ >From Mark.R.Valence@dartmouth.edu (kurash@dartmouth.edu) Date: 25 Feb 1994 18:37:55 GMT Organization: Dartmouth College, Hanover, NH In article Jim.Matthews@dartmouth.edu (Jim Matthews) writes: > In article <2ki0ku$pir@news.kth.se>, d88-jwa@mumrik.nada.kth.se (Jon Wtte) > wrote: > > > What I do is I patch the QuickDraw text measurement and text > > drawing bottlenecks to measure a string of bullets instead of > > the real string. > > I tried that once but found it difficult to tell when StdText and StdMeas > were being called for the password, as opposed to anything else in the > dialog. Is there a sure-fire way to do this? I tried patching the screen driver and watched for the proper bit pattern of the real password characters, then replaced the bits with a bullet pattern. I never did get that to work... ;-) There are two main weaknesses of using a "bullet font" (or the StdText method) to hide a password in a dialog box edittext item. First, anyone can grab the password by choosing Copy from the Edit menu (under Sys7). This is not an issue unless the user has a habit of typing a password and leaving the dialog on the screen. The more important drawback is that it is difficult to handle two-byte character sets. Because the font would be script specific, extra "bullet" characters would be emitted. The source below solves the password-in-a-dialog problem by filtering the event stream and modifying the proper key-down events. It keeps a private copy of the password. Although this implementation does not support multibyte character sets, it could be modified to do so easily (and in fact I am going to have to do this eventually myself). The PassFilter routine uses another dialog filter routine that handles the non-password related stuff (OK and Cancel keyboard equivalents, etc.) You need to write this y'self. On a side note, I always liked the way the original StuffIt (I think) handled the archive password. It just changed the font size to something like 2, and used PICTs for the "static text" (there were no non-password edit text items). Cute. Mark. - -------------------------------------------------------------------- "On the Internet, nobody knows you're a dog." Ice Peak Form Mice Elf -- cartoon in New Yorker /* * (c)1994 Mark Valence * * Permission to use and alter this source is * granted, provided that you do not transmit * the resulting password in cleartext over a * network (unless required by the protocol). */ #include #include #include #include #include #include /* * example of usage: * * PassData pdata; * Str255 mypass; * * ... * pdata.passitem = MY_PASSWORD_ITEM; * pdata.passmax = 8; * pdata.bullet = '*'; * pdata.password = mypass; * *mypass = 0; * SetWRefCon(dialog, (long)&pdata); * ModalDialog((ProcPtr)PassFilter, &item); * ... */ /* * a pointer to this structure is placed in the refCon * of the dialog box that contains the password item. * the buffer that 'password' points to must be at * least 'passmax'+1 bytes (one byte for the length), * and must initially be zero-length. */ typedef struct t_passdata { short passitem; /* dialog item number of password text */ short passmax; /* maximum length of password */ char bullet; /* special character to use */ StringPtr password; /* pointer to a buffer for the real password */ } PassData; /* * this routine must be linked in from another source * it is responsible for handling special keystrokes * such as , , , Cmd-., etc. * UpdtFilter also handles window update events for * application windows and the Edit menu command keys. */ pascal Boolean UpdtFilter (DialogPtr dialog, EventRecord *event, short *item); /* * these routines are included below for completeness */ char *pstrdel (unsigned char *s, int ix, int len); char *pstrins (unsigned char *s, unsigned char c, int ix); pascal Boolean PassFilter (DialogPtr dialog, EventRecord *event, short *item) { PassData *passp; short selStart, selEnd; unsigned char ch; Str255 hold; short kind; Handle h; Rect r; /* take care of return, enter, cmd-., * escape, updates, Edit menu, etc. */ if (UpdtFilter(dialog, event, item)) return(true); passp = (PassData *)GetWRefCon(dialog); if (!(event->modifiers & cmdKey) && (event->what == keyDown || event->what == autoKey) && (((DialogPeek)dialog)->editField == (passp->passitem - 1))) { ch = event->message & charCodeMask; selStart = (**(((DialogPeek)dialog)->textH)).selStart; selEnd = (**(((DialogPeek)dialog)->textH)).selEnd; switch (ch) { case 0x08: /* backspace */ if (selEnd != selStart) pstrdel(passp->password, selStart + 1, selEnd - selStart); else if (selStart > 0) pstrdel(passp->password, selStart, 1); break; case 0x09: /* tab */ case 0x1C: /* left arrow */ case 0x1D: /* right arrow */ case 0x1E: /* up arrow */ case 0x1F: /* down arrow */ break; default: BlockMove(passp->password, hold, sizeof(hold)); pstrdel(hold, selStart + 1, selEnd - selStart); pstrins(hold, ch, selStart + 1); if (*hold > passp->passmax) { event->what = nullEvent; SysBeep(1); } else { BlockMove(hold, passp->password, *hold + 1); event->message &= 0xFFFFFF00; event->message |= passp->bullet; } break; } GetDItem(dialog, ok, &kind, &h, &r); HiliteControl((ControlHandle)h, (*passp->password ? 0 : 255)); } return(false); } char * pstrdel (unsigned char *s, int ix, int len) { int last; if (len == 0 || ix > *s) return(s); last = ix + len; if (last > *s) { *s = ix - 1; } else { BlockMove(&s[last], &s[ix], *s - last + 1); *s -= len; } return(s); } char * pstrins (unsigned char *s, unsigned char c, int ix) { if (*s < 0x00FF) (*s)++; BlockMove(&s[ix], &s[ix + 1], *s - ix); s[ix] = c; return(s); } +++++++++++++++++++++++++++ >From kjohnso@nyx10.cs.du.edu (Kai) Date: Fri, 4 Mar 94 21:26:04 GMT Organization: Nyx, Public Access Unix at U. of Denver Math/CS dept. In article <2klgi3$36o@dartvax.dartmouth.edu>, kurash@dartmouth.edu wrote: >In article >Jim.Matthews@dartmouth.edu (Jim Matthews) writes: > >There are two main weaknesses of using a "bullet font" (or the StdText >method) to hide a password in a dialog box edittext item. First, >anyone can grab the password by choosing Copy from the Edit menu (under >Sys7). This is not an issue unless the user has a habit of typing a >password and leaving the dialog on the screen. > >The more important drawback is that it is difficult to handle two-byte >character sets. Because the font would be script specific, extra >"bullet" characters would be emitted. > >The source below solves the password-in-a-dialog problem by filtering >the event stream and modifying the proper key-down events. It keeps a >private copy of the password. Although this implementation does not >support multibyte character sets, it could be modified to do so easily >(and in fact I am going to have to do this eventually myself). > >[source deleted...] You can do the same trick and support all the standard TextEdit things by putting a hidden TE item offscreen and rerouting key events to it. Just keep the selections in the two items in sync, and match the number of bullets in the visible item to the hidden one. The user can copy the password all they want, but they just get bullets. I think this is how the sample code in the H/I notes from Apple works... Oh, if you're doing passwords, you should have a look at the note about them, there are some standard ways for handling all the clicks and key presses. I can probably find both the H/I note and the sample code if you but me about it. -Kai +++++++++++++++++++++++++++ >From moofster@world.std.com (A Happy Dog-Cow) Date: Sun, 6 Mar 1994 05:36:58 GMT Organization: The Nest of the Moofster Sheesh! All of this talk of patching traps & weirdo fonts to just make a password entry screen! Programmers should be on guard against innapropriate over-engineering!! Sheesh! Just make a ModalDialogFIlter procedure, intercept the update routine for the item(s) in question, and voila. Patching traps or coming up with exotic fonts to perform this is unnecessary! Robert M. Seretny, Armesti Research, (Macintosh/SCSI guru for short-term hire; email moofster@world.std.com) +++++++++++++++++++++++++++ >From danprice@delphi.com Date: Mon, 7 Mar 94 18:55:47 -0500 Organization: Delphi (info@delphi.com email, 800-695-4005 voice) I dunno, I wrote a short routine for a friend in a comp/sci course who wanted to impress his teacher. Basically, I set up a dialog with 12 buttons, in a numeric keypad arrangement. The things that's neat about this is that, unless the "hacker" is extremely clever, he won't be able to use a filter (sorry, not a filter) a trap patch to intercept the passcode, as the difficulty of figuring which part of the screen clicked is fairly high. Also, I thought about randomly scrambling the buttons in the dialog, to make this _even_ harder, as well as to foil those with binoculars and such. I think this whole password thing is overkill.... -dp --------------------------- >From python@jhunix.hcf.jhu.edu (Bryan Arntson) Subject: Permanent front windows... Date: 3 Mar 1994 17:53:33 -0500 Organization: Homewood Academic Computing, Johns Hopkins University, Baltimore, Md, USA I apologize for not knowing what these windows are called, but how do I create those windows that are ALWAYS in the front. They look like little fake windows. They have B&W window titles, that are about 10 pixels high, and then the window below them. What are these called? And most importantly, HOW DO I CREATE ONE? Could someone post, or send me, a short code on the subject? Thanks in advance, Bryan python@jhunix.hcf.jhu.edu +++++++++++++++++++++++++++ >From troy@i-link.com (Troy Gaul) Date: 3 Mar 1994 23:24:53 -0600 Organization: I-Link, Ltd., Des Moines, IA In article <2l5ppdINN5qk@jhunix.hcf.jhu.edu>, Bryan Arntson wrote: >I apologize for not knowing what these windows are called, but how do I >create those windows that are ALWAYS in the front. There are several names that are used, including 'Utility Window', 'Tool Window', 'Palette', 'Windoid', 'Floating Window', and 'Floater'. >They look like little >fake windows. They have B&W window titles, that are about 10 pixels high, >and then the window below them. They don't _have_ to have a B&W window title. The only reason that I can think of that many of them are B&W is that the programmers didn't know about the Infinity Windoid WDEF (which, it happens, I wrote), which gives you a System 7-style coloring scheme (but is also compatible with System 6). It gives these to you for free, as it is freeware, and worry-free (it's been well tested, and the source is included). >What are these called? And most >importantly, HOW DO I CREATE ONE? Could someone post, or send me, a short >code on the subject? You can make a window with this type of a titlebar by getting the Infinity Windoid WDEF from the anonymous FTP site: ftp://ftp.i-link.com/pub/infsys/ This WDEF does not help you make the window float on top of the others, however. To do this, you need a floating window library. There was one included with Develop 15, and updated code was included with Develop 16. You can pick up the latest version of that code, along with the text of the article (through an arrangement I make with Apple), in the same place. _troy -- //////// ////// Troy Gaul t-gaul@i-link.com // // // I-Link, Ltd. // // // // "Iungo ergo sum." (I-Link, therefore I am.) // // ////// __________________________________________________________ // +++++++++++++++++++++++++++ >From kurisuto@chopin.udel.edu (Sean J. Crist) Date: 4 Mar 1994 11:37:41 -0500 Organization: University of Delaware >This WDEF does not help you make the window float on top of the others, >however. To do this, you need a floating window library. There was one >included with Develop 15, and updated code was included with Develop 16. >You can pick up the latest version of that code, along with the text of >the article (through an arrangement I make with Apple), in the same place. Or, for that matter, you could just write your own routines to do this. This only took me a few hours to do. Basically, you've got to rewrite the top level of the window manager. A good start is to write a routine that acts like SelectWindow (calling ShowHide and HiliteWindow) except that it leaves your Palette window in front. Then go through your code and do a global search-and-replace to change SelectWindow to the name of your replacement routine. If you can get that much working properly, that's 90% of the game. If there's interest, I can post my code; it's pretty complicated, though, because I'm doing a lot more than just supporting floating palettes. Rather than keep a million WindowPtr's to everything (which is messy when your application allows the user to open any number of instances of a particular type of window), I keep information about the window in a handle stored in the window's RefCon. Then when I need window number X of type Y, I call one of my routines to quickly search through the linked list of windows to try to find a match. I can clean up this code a little and post it if there's interest. --Sean (kurisuto@chopin.udel.edu) \/ __ __ _\_ | If restaurants were named as gay organizations are, --- | | \ / | "McDonald's" would be called "Meat, Bread, Vegetables, _| ,| ,| ----- | Beverages, Condiments, and Friends" (MBVBCF for short). _| ,| ,| [_] |-------------------------------------------------------- | | | [_] | Finger this account for a copy of the Bill of Rights. --------------------------- >From andersw@hum.gu.se (Anders Wahlin) Subject: Preference file question! Date: Fri, 4 Mar 1994 08:03:28 GMT Organization: Hum Fak:s Dataservice Almost every program has a preference file. I have twoo very simple questions about this. 1¥ Is it "wrong" to have a resource file as a preference file? 2¥ How can I create an icon on my preference file, within the program? Thanks! -- Anders Wahlin andersw@hum.gu.se +++++++++++++++++++++++++++ >From rmah@panix.com (Robert S. Mah) Date: Fri, 04 Mar 1994 04:52:40 -0500 Organization: One Step Beyond andersw@hum.gu.se (Anders Wahlin) wrote: > Almost every program has a preference file. I have twoo very simple > questions about this. > > 1 Is it "wrong" to have a resource file as a preference file? No, many programs use resources to store their prefs. The only drawback is that the file is no longer platform independent. I've often thought of using a text file to store prefs. > 2 How can I create an icon on my preference file, within the program? Simply add an entry into your BNDL resource with associated FREF and ICN#/icl/ics resources. However, please think about using the standard 'pref' file type. The finder will give it a nice prefs style icon and people's preferences folder will open just a bit faster. Now if everyone did this... Cheers, Rob ________________________________________________________________________ Robert S. Mah One Step Beyond rmah@panix.com +++++++++++++++++++++++++++ >From Lars.Farm@nts.mh.se (Lars Farm) Date: Fri, 04 Mar 1994 11:33:02 +0100 Organization: Mid Sweden University In article , andersw@hum.gu.se (Anders Wahlin) wrote: > 1¥ Is it "wrong" to have a resource file as a preference file? No. It's common practice. > 2¥ How can I create an icon on my preference file, within the program? Set the file type to 'pref'. Lars -- Lars.Farm@nts.mh.se +++++++++++++++++++++++++++ >From peter@ncrpda.curtin.edu.au (Peter N Lewis) Date: 5 Mar 1994 21:14:20 +0800 Organization: NCRPDA, Curtin University rmah@panix.com (Robert S. Mah) writes: >However, please think about using the standard 'pref' file type. The >finder will give it a nice prefs style icon and people's preferences folder >will open just a bit faster. Now if everyone did this... Do this - it's much nicer. I used to do it the other way with a BNDL and icon for the prefs file, but the Preferences folder is full up with thousands of different icons, it's just a mess. So use the 'pref' file type, and don't worry about designing an icon, and life will be good. Peter. -- Peter N Lewis Ph: +61 9 368 2055 +++++++++++++++++++++++++++ >From perm@csd.uu.se (Per Mildner) Date: 11 Mar 1994 14:56:23 GMT Organization: Computing Science Dept.,Uppsala University, Sweden Several people have suggested using the 'pref' file type for preference files. There is one problem with this, this is the type for the finder prefs. Most people thinks this is a good thing as this automagically gives the pref file a good icon, but the people suggesting this are not likely to use balloon help in the finder :-) If you use the pref file you better add some balloon info in your pref file too. (Another potential problem might be with EasyOpen or whatever which I have not used). Regards, -- Per Mildner Per.Mildner@CSD.UU.SE Computing Science Dept. tel: +46 18 181049 Uppsala University, Sweden fax: +46 18 521270 +++++++++++++++++++++++++++ >From t-gaul@i-link.com (Troy Gaul) Date: Fri, 11 Mar 1994 12:35:25 -0600 Organization: I-Link, Ltd. In article , perm@csd.uu.se (Per Mildner) wrote: > Several people have suggested using the 'pref' file type for > preference files. There is one problem with this, this is the type > for the finder prefs. Most people thinks this is a good thing as this > automagically gives the pref file a good icon, but the people > suggesting this are not likely to use balloon help in the finder :-) > If you use the pref file you better add some balloon info in your pref > file too. I really don't think this is a big issue against using that as a file type. Besides, I have several other pieces of Apple software (the Apple Modem Tool was the one I saw when I checked this out) that also do the same thing. > (Another potential problem might be with EasyOpen or > whatever which I have not used). I don't see where this would be a problem. Actually, quite the opposite is true. If you have the resources for Easy Open in your application, then you can describe the preferences file with a 'kind' resource as 'MyApplication preferences', and this would appear in the Finder names lists of the preferences folder (or the get info box). Easy Open uses the creator of the file to determine its labeling, apparently, the Balloon help in the Finder doesn't look at the creator of the file when the cursor's pointed at a 'pref' file as it should. I've taken the advice to use 'pref' as the file type and to NOT include an icon for that type to heart. I'm doing it in most of my own programming projects now. _troy //////// //////___Troy Gaul_________________________t-gaul@i-link.com__ // // // I-Link, Ltd. ; West Des Moines, Iowa // // // // "Iungo ergo sum." (I-Link, therefore I am.) // // //////________________________________________________________ // --------------------------- >From pope@imv.aau.dk (Povl H. Pedersen) Subject: Reading PICT files != 72 dpi. How ? Date: 26 Feb 1994 16:01:21 GMT Organization: Information and Media Science, Aarhus University, DENMARK I am working on a small custom image modifying program, and it will have to load in PICT files created in other applications. I have managed to steal some code that will rwad/write PICT files, but my problem now is, that the end user somethimes generates PICTs in a better resolution than 72 dpi. When he reads them in, they are shrinked to keep size as the original, and he then loses information. How do I read in PICT files with all osrts of resolution, handle them as pixel-by-pixel images, and then finally write them back with their original resolution info ? thanks in advance, - - Povl H. Pedersen - Macintosh Consultant and Programmer pope@imv.aau.dk (preferred) / povlphp@uts.uni-c.dk "Macintosh...for those who can see through Windows!" +++++++++++++++++++++++++++ >From pope@imv.aau.dk (Povl H. Pedersen) Date: 28 Feb 1994 18:16:17 GMT Organization: Information and Media Science, Aarhus University, DENMARK I wanted to know how I could read in a PICT in a higher than 72dpi resolution, and keep every single pixel. I tried the net, as it is usual a good fast reference manual ;^) The net did not want to answer me, so I did spend some time, and found a working way. I am using information on page 17-24 of Inside Macintosh volume VI. This info is not documented in any headers anywhere, but I suppose it is safe to use. (Now, why has Apple not given us routines to read/write PICT files ? They should be a natural part of the toolbox. Just like some way to get a PicHandle from a pixmap). My ugly code is enclosed below. I did slight editing after copy/pasting, so it may contain a few syntax errors. My routine allocates a new offscreen GWorld, and reads the picture in here. Only minimum level of error checking is done. The application where this is used will not be run on large images on machines with less than 32-64 MB RAM. So memory is no problem. This is one reason I make the offscreen pixmap 32 bits instead of using the information from the file. Another reason is, that I parse all pixels in a loop that expects 32bit pixmap. Disclaimer: This code is guaranteed to be incompatible with at least one version of one Microsoft product. Not necesarily now, but then in the future. Don't blame me. Blame the guilty ones. Povl - ----------------------------- // structure not defined anywhere. Contents just listed in IM VI, page 17-24 typedef struct { unsigned short picSize; Rect picFrame; // Now comes the header as displayed in IM VI, but not defined in any headers short s1; // = 0x0011 for special resolution short s2; // = 0x02FF short HeaderOp; // Opcode for PICT command. 0x0C00 = header short version; // = -2 for extended version 2 pict file short reserved; Fixed hRes; // horizontal resolution Fixed vRes; // vertical resolution Rect srcRect; // Native source rectangle // More stuff follows but is ignored } myVersion2PICTHeaderT; static short gPICT_FILE_RESNUM; // Quickdraw bottleneck routine to do the hard work pascal void GetPICTData( Ptr dataPtr, short byteCount ) { long longCount; longCount = byteCount; err = FSRead( gPICT_FILE_RESNUM, &longCount, dataPtr ); } // This routine takes the following parametres: // p: a pointer to a GWorldPtr. On exit it will point to a new GWorld. // filespec: FSSpec pointer that identifies the PICT file to read. void getPICTFile( GWorldPtr *p, FSSpec *fileSpec) { QDProcsPtr savedProcs; CQDProcs myProcs; GDHandle gdh; CGrafPtr port; PicHandle thePic = nil; long longCount; short h, w; Rect r,gr; PictInfo pinfo; Fixed vRes, hRes; // horizontal/vertical resolutions myVersion2PICTHeaderT myPICTheader; *p = nil; // lazy way to return error // Open file and skip old MacPaint header err = FSpOpenDF( fileSpec, fsRdPerm, &gPICT_FILE_RESNUM ); SetFPos( gPICT_FILE_RESNUM, fsFromStart, 512); // skip header // clear my header. memset( &myPICTheader, 0, sizeof(myPICTheader) ); // Get the IM VI documented header longCount = sizeof( myPICTheader ); err = FSRead( gPICT_FILE_RESNUM, &longCount, &myPICTheader ); if (err != noErr) { TellUser( "Unpected End-of-File. Replace user and try again"); return; } // Test if we have an extendended version 2 pict header if ( myPICTheader.s1 == 0x0011 && myPICTheader.s2 == 0x02FF && myPICTheader.HeaderOp == 0x0C00 && myPICTheader.version == -2) { // Now we have a PICTure of another resolution hRes = myPICTheader.hRes; vRes = myPICTheader.vRes; } else hRes = vRes = Long2Fix( 72 ); // default resolution // skip back to header again, loading pict should start at pos=512 SetFPos( gPICT_FILE_RESNUM, fsFromStart, 512); // Get room for the real header and read it thePic = (PicHandle) NewHandle(sizeof(Picture)); longCount = sizeof( Picture ); FSRead( gPICT_FILE_RESNUM, &longCount, (Ptr) *thePic ); // different resolution, use the info from our version 2 extended header if (hRes != Long2Fix( 72 )) { w = myPICTheader.srcRect.right - myPICTheader.srcRect.left; h = myPICTheader.srcRect.bottom - myPICTheader.srcRect.top; r = myPICTheader.srcRect; } else { // just use the data the old way w = (**thePic).picFrame.right; h = (**thePic).picFrame.bottom; r = (**thePic).picFrame; } // Now that we have the header, we know which size to make our offscreen buffer GetGWorld( &port, &gdh ); SetRect( &gr, 0, 0, w, h ); err = NewGWorld( p, 32, &gr, (CTabHandle) 0, (GDHandle) 0, 0 ); if (err != noErr) DoCrashTheMachineAndAnnoyTheEndUser(); SetGWorld( *p, nil ); // Set our resolution. This makes sure the usual save routine will // write it back for whatever DPI we use. (*p->portPixMap)->vRes = vRes; (*p->portPixMap)->hRes = hRes; // SetStdCProcs SetStdCProcs( &myProcs ); myProcs.getPicProc = GetPICTData; savedProcs = ((GrafPtr) p)->grafProcs; ((CGrafPtr) p)->grafProcs = &myProcs; // this line does the real work DrawPicture( thePic, &r ); SetGWorld( port, gdh ); FSClose( gPICT_FILE_RESNUM ); DisposHandle( (Handle) thePic ); ((GrafPtr) p)->grafProcs = savedProcs; } - - Povl H. Pedersen - Macintosh Consultant and Programmer (For hire). System Administrator at the Aarhus Engineering School pope@imv.aau.dk (preferred) / povlphp@uts.uni-c.dk "Macintosh...for those who can see through Windows!" --------------------------- >From temple@itd.nrl.navy.mil (Dr. Jon Gerard Temple) Subject: Resources on PowerPC Date: Fri, 11 Mar 1994 19:56:23 GMT Organization: Naval Research Laboratory There is an issue I have a little trouble with: it is my understanding that Native applications on the Power Macintosh will not use resources (or the resource fork.). What does this mean for programmers that are used to ResEdit for creating/editing resources, whose code points to reusable resources, etc? Will this feature of Mac programming simply cease to exist when writing Native RISC applications or is there an alternative approach that will treat part of the DATA fork on PPC Macs as editable, callable, reusable resources that a new version of ResEdit (DataEdit??) will able to work with? Ideas? +++++++++++++++++++++++++++ >From minnis@cobaf.unt.edu (Minnis, Robert) Date: Fri, 11 Mar 1994 20:15:23 GMT Organization: College of Business Administration, UNT In article temple@itd.nrl.navy.mil (Dr. Jon Gerard Temple) writes: >From: temple@itd.nrl.navy.mil (Dr. Jon Gerard Temple) >Subject: Resources on PowerPC >Date: Fri, 11 Mar 1994 19:56:23 GMT >There is an issue I have a little trouble with: it is my understanding >that Native applications on the Power Macintosh will not use resources >(or the resource fork.). What does this mean for programmers that are >used to ResEdit for creating/editing resources, whose code points to >reusable resources, etc? Will this feature of Mac programming simply >cease to exist when writing Native RISC applications or is there an >alternative approach that will treat part of the DATA fork on PPC Macs >as editable, callable, reusable resources that a new version of ResEdit >(DataEdit??) will able to work with? >Ideas? >From what I understand, resources are not going to vanish. PPC code will be stored in the data fork (68K code will still be stored in CODE resources). Robert Minnis +++++++++++++++++++++++++++ >From peirce@outpost.SF-Bay.org (Michael Peirce) Date: Fri, 11 Mar 94 15:39:49 PST Organization: Peirce Software, Inc. In article (comp.sys.mac.programmer), temple@itd.nrl.navy.mil (Dr. Jon Gerard Temple) writes: > There is an issue I have a little trouble with: it is my understanding > that Native applications on the Power Macintosh will not use resources > (or the resource fork.). What does this mean for programmers that are > used to ResEdit for creating/editing resources, whose code points to > reusable resources, etc? Will this feature of Mac programming simply > cease to exist when writing Native RISC applications or is there an > alternative approach that will treat part of the DATA fork on PPC Macs > as editable, callable, reusable resources that a new version of ResEdit > (DataEdit??) will able to work with? Resourse do *not* go away on the Power Mac. PowerPC executable code is not found in CODE resources (though it can be found in a few special code resources) rather in the data fork. Still, all other "normal" Mac resources are still around and used. In fact, CODE resource can still contain 68K code - this is how you implement fat binaries. So relax, ResEdit isn't going away. -- Michael Peirce -- peirce@outpost.sf-bay.org -- Peirce Software, Inc. -- 719 Hibiscus Place, Suite 301 -- -- San Jose, California USA 95117 -- Makers of: Smoothie & -- voice: +1.408.244.6554 fax: +1.408.244.6882 -- Peirce Print Tools -- AppleLink: peirce & America Online: AFC Peirce +++++++++++++++++++++++++++ >From richardb@cocytus.demon.co.uk (Richard Buckle) Date: Sat, 12 Mar 1994 12:57:25 GMT Organization: None In article peirce@outpost.SF-Bay.org (Michael Peirce) writes: > >... >Resourse do *not* go away on the Power Mac. PowerPC executable code >is not found in CODE resources (though it can be found in a few special >code resources) rather in the data fork. Still, all other "normal" >Mac resources are still around and used. In fact, CODE resource can >still contain 68K code - this is how you implement fat binaries. >... Arrgggh! How could Apple do this to me? I need my data forks for DATA. A major part of my job is writing computationally *very* intensive XCMDs (for HyperCard) and CODE resources (for Excel). These are of course stored in the resource forks of stacks and spreadsheets and we need to turn them into fat binaries. And HyperCard and Excel expect to call CODE and XCMD resources, not any other type. Will it be possible to have 68K stub resources call 'special' PowerPC executable resources? If not, I guess I shall have to store the PowerPC code in the data fork of another file. As new releases are very frequent this would be an installation nightmare. Would the new Shared Library Manager help at all? BTW, how is the global A4 addressing issue handled in PowerPC standalone code? Replies by mail please -- I shan't have time to read much news next week. I shall summarise in c.s.m.p when the shouting is over. Apologies if these are RTFM-type questions -- we have not yet taken delivery of CodeWarrior so I am rather in the dark. - - Richard Buckle richardb@cocytus.demon.co.uk richardb@cix.compulink.co.uk +++++++++++++++++++++++++++ >From wdh@netcom.com (Bill Hofmann) Date: Sat, 12 Mar 1994 20:00:40 GMT Organization: NETCOM On-line Communication Services (408 241-9760 guest) richardb@cocytus.demon.co.uk (Richard Buckle) writes: >A major part of my job is writing computationally *very* intensive XCMDs (for >HyperCard) and CODE resources (for Excel). These are of course stored in the >resource forks of stacks and spreadsheets and we need to turn them into fat >binaries. And HyperCard and Excel expect to call CODE and XCMD resources, not >any other type. This seems to be enough of a FAQ that I've responded here as well as directly. Michael misspoke himself slightly: BY DEFAULT, PowerPC code for APPLICATIONS lives in the data fork of the file. What this means is: * PPC application code can be in the data fork * PPC application code can be in one huge resource You just have to set up the (mandatory) 'cfrg' resource properly. Also: * standalone code resource can be all 680x0 * standalone code resources can be all PowerPC * standalone code resources can be "fat", containing both If standalone code will only be called from 680x0 code, * it can be plain vanilla 680x0 code, like today * it can be PPC code with a "RoutineDescriptor" at the front * it can be "fat" with a "RoutineDescriptor" at the front 680x0 code doesn't need to know about the PowerPC AT ALL. If standalone code will only be called from PowerPC code, * it can be naked PPC code * it can be PPC code with a RoutineDescriptor * it can be 680x0 code with a RoutineDescriptor * it can be "fat" with a RoutineDescriptor * it can be naked 680x0 code In all but the FIRST (native PPC), it must be called using a special routine. So if you write PPC-aware code, you need to read the MixedMode manager chapter of the Mac on RISC SDK. If standalone code may be called from either 680x0 or PPC: * it can be naked 680x0 code * it can be PPC code with a RoutineDescriptor * it can be 680x0 code with a Routine Descriptor * it can be "fat" with a RoutineDescriptor Since not all of the ToolBox and OS are native, ANY standard code resource that contains PPC code MUST have a routine descriptor. That goes for things like XCMDs as well. I think that about covers it. Whoever maintains the FAQ might want to put this in there. Oh yes, Apple Developer University is offering a course called "PowerPC Boot Camp", which covers this and lots more. It's a four day course, with plenty of hands-on, including code resource kinda stuff. I'm one of the Drill Sargeants, oops, instructors, so, I have an ulterior motive. -- -Bill Hofmann wdh@netcom.COM Fresh Software and Instructional Design +1 510 524 0852 +++++++++++++++++++++++++++ >From Mark_Day@powertalk.apple.com (Mark Day) Date: Sat, 12 Mar 1994 00:11:42 GMT Organization: Apple Computer, Inc. In article , temple@itd.nrl.navy.mil (Dr. Jon Gerard Temple) wrote: > There is an issue I have a little trouble with: it is my understanding > that Native applications on the Power Macintosh will not use resources > (or the resource fork.). What does this mean for programmers that are > used to ResEdit for creating/editing resources, whose code points to > reusable resources, etc? Will this feature of Mac programming simply > cease to exist when writing Native RISC applications or is there an > alternative approach that will treat part of the DATA fork on PPC Macs > as editable, callable, reusable resources that a new version of ResEdit > (DataEdit??) will able to work with? > > Ideas? The code for native applications is normally found in the data fork, not a bunch of CODE resources (for non-native code). You can (and should) still use resources. In fact, you can have a "fat" application with both CODE resources and native code in the data fork, that share other non-code resources (like strings, icons, etc.). Such "fat" applications will execute the native code on Power Macintosh or the old 68K CODE resources on non-Power Macintoshes. -- Mark Day, Apple Computer, Inc. mday@apple.com --------------------------- >From neeri@iis.ee.ethz.ch (Matthias Neeracher) Subject: Safer Segments ? Date: 15 Mar 94 16:49:06 Organization: Integrated Systems Laboratory, ETH, Zurich My program usually has multiple resource files open, some of which contain CODE resources (they are similar to AppleScript droplets). Unfortunately, if _LoadSeg is called while one of the other CODE containing resource forks is in front of the resource chain, a nasty crash results. So far, I have been able to work around this problem by calling UseResFile() in all the right places, but I'd prefer to know a simpler solution, if one exists. Any ideas? Matthias - --- Matthias Neeracher neeri@iis.ee.ethz.ch "I really don't want the SNMP agent controlling my toilet to tell someone when/where I'm using it." -- Sean Graham +++++++++++++++++++++++++++ >From wysocki@netcom.com (Chris Wysocki) Date: Wed, 16 Mar 1994 10:02:35 GMT Organization: Global Village Communication, Mountain View, CA In article neeri@iis.ee.ethz.ch (Matthias Neeracher) writes: >My program usually has multiple resource files open, some of which contain CODE >resources (they are similar to AppleScript droplets). Unfortunately, if >_LoadSeg is called while one of the other CODE containing resource forks is >in front of the resource chain, a nasty crash results. So far, I have been able >to work around this problem by calling UseResFile() in all the right places, >but I'd prefer to know a simpler solution, if one exists. It's hardly simple, but the most robust thing to do is to patch _LoadSeg and have your patch set the current resource file, call the "real" _LoadSeg and restore the previous resource file on the way out. Patching _LoadSeg also allows you to preflight the loading of the code resources so that you can avoid crashing in the event that the Segment Loader can't load the segment. I've use this technique in a number of applications and it works quite well; if you have MacApp 3.x, take a look at UMemory.cp and UMemory.a to see how it can be done. Chris. +++++++++++++++++++++++++++ >From Greg_Marriott@genmagic.com (Greg Marriott) Date: Thu, 17 Mar 1994 02:26:31 -0800 Organization: General Magic, Inc. neeri@iis.ee.ethz.ch (Matthias Neeracher) wrote: > [...] if _LoadSeg is called while one of the other CODE > containing resource forks is in front of the resource chain, a nasty > crash results. So far, I have been able to work around this problem > by calling UseResFile() in all the right places, [...] > > Any ideas? I don't know if you'll think this is simpler or not... You might try patching _LoadSeg to call UseResFile() before jumping to the original code. -- Greg Marriott Just Some Guy General Magic, Inc. Disclaimer: My opinions are not necessarily the same as General Magic's. (can a company even HAVE an opinion?) +++++++++++++++++++++++++++ >From ari@world.std.com (Ari I Halberstadt) Date: Thu, 17 Mar 1994 21:08:39 GMT Organization: The World Public Access UNIX, Brookline, MA In article , Matthias Neeracher wrote: >My program usually has multiple resource files open, some of which contain CODE >resources (they are similar to AppleScript droplets). Unfortunately, if >_LoadSeg is called while one of the other CODE containing resource forks is >in front of the resource chain, a nasty crash results. So far, I have been able >to work around this problem by calling UseResFile() in all the right places, >but I'd prefer to know a simpler solution, if one exists. You can patch the _LoadSeg trap. Here's the code I use to patch LoadSeg. It checks that there's enough memory available before loading the segment. If you add a call to UseResFile just before and after the GetResource call it should do what you need. The PatchType structure contains info about the patch that you'd set when installing the patch, though you could just use some global variable to hold the address of the routine returned by NGetTrapAddress. /* data needed by a patch */ typedef struct PatchType { struct PatchType *next; /* next patch */ pascal void (*addr)(...); /* address of patch routine */ pascal void (*trap)(...); /* saved trap address */ TrapType type; /* type of trap */ short num; /* number of trap */ Boolean installed; /* true if patch was installed */ } PatchType, *PatchPtr, **PatchHandle; /* The PATCH_ENTER macro should be the first executable statement in your patch routine. PATCH_ENTER saves all of the registers and sets up register a5. PATCH_ENTER also ensures that the routine has a stack frame so that the PATCH_RETURN macro can be used. */ #define PATCH_ENTER() \ { long _patch_force_stack_frame; { /* force stack frame of at least 4 bytes */ \ asm { movem.l a0-a5/d0-d7, -(sp) } /* save registers */ \ asm { move.l #0x0904, a5 } /* setup register a5 */ \ asm { move.l (a5), a5 } // this PATCH_RETURN macro magically restores registers d0-d7/d0-a7 to the // same values they had when it was entered, which makes it a pretty // safe way to patch traps (note: well, i've only been using this code // for about a week, but i stepped through it and it should work). /* The PATCH_RETURN macro jumps to the address of the originally patched routine. You should call PATCH_RETURN at the end of your patch. The 'patch' parameter should be a pointer returned from PatchBegin. The compiler must generate a stack frame (using register a6) for the patch routine. This should be ensured by the PATCH_ENTER macro. */ #define PATCH_RETURN(patch) \ } } \ { \ asm { move.l a6, a1 } /* get current value of a6 */ \ asm { move.l (a6), -(a6) } /* shift location of saved a6 */ \ asm { move.l patch, a0 } /* get pointer to patch record */ \ asm { move.l PatchType.trap(a0), (a1) } /* put patched routine's address on stack */ \ asm { movem.l (sp)+, a0-a5/d0-d7 } /* restore registers */ \ asm { unlk a6 } /* pop stack frame */ \ asm { rts } /* return to patched routine */ \ } static PatchType *gPatchLoadSeg; /* data about patch */ /* get a code resource */ static Handle GetCodeResource(ResID id) { Handle code; require(LMGetResLoad()); SetResLoad(false); code = GetResource('CODE', id); SetResLoad(true); FailNILRes(code); /* We use MemAvailableNoCushion since MemAvailable could unload segments, and if segments are unloaded from within this patch the program crashes. */ if (! *code && ! MemAvailableNoCushion(SizeResource(code))) FailOSErr(memFullErr); SetResAttrs(code, GetResAttrs(code) & ~resLocked); FailResError(); LoadResource(code); FailResError(); return(code); } /* For its own reasons, perhaps related to using FAR code, THINK C seems to patch the _LoadSeg trap. THINK C also makes code resources locked. Unfortunately, this prevents _LoadSeg from calling MoveHHi on segments, even if the low-memory global SegHiEnable is non-zero. Having code segments low in memory leads to severe heap fragmentation when pointers are allocated above the code segments. This patch will load the resource, move it to the top of the heap, and lock it there. This patch will also trigger an exception if the resource couldn't be loaded or if there isn't enough memory to load the resource. */ static pascal void PatchLoadSeg(ResID segnum) { Handle code; PATCH_ENTER(); code = GetCodeResource(segnum); if (code && LMGetSegHiEnable()) { MoveHHi(code); HLock(code); } PATCH_RETURN(gPatchLoadSeg); } // this has nothing to do with the above patch, but could be useful // to someone who wants to load a segment pascal void LoadSegTrap(ResID seg) = _LoadSeg; /* load the segment */ static void LoadSeg(ResID seg) { asm { move.w seg, -(sp) bra.s @1 /* call LoadSeg */ bra.s @2 /* LoadSeg returns here */ nop /* fill up two bytes */ @1: LoadSegTrap @2: } } -- Ari Halberstadt ari@world.std.com #include "These beetles were long considered to be very rare because very few entomologists look for beetles in the mountains, in winter, at night, during snow storms." -- Purves W. K., et al, "Life: The Science of --------------------------- >From mssmith@afterlife.ncsc.mil (M. Scott Smith) Subject: Speeding up animation; questions Date: Sun, 27 Feb 1994 23:49:11 GMT Organization: The Great Beyond Ramble alert! (This one's kinda long..) Hi gang! I found a few minutes this weekend to revisit my much-procrastinated tour into the development of Mac arcade games.. (Well, I haven't really procrastinated, I just haven't had the time. :( I've been developing a direct-screen animation toolkit which I'll (eventually) be using to write games. I'm now working on the "animation engine" -- the heart of the game where all of the animation will be performed. What I'll do is describe the method(s) I'm thinking about using. Any comments on my methods would be greatly appreciated; don't hesitate to tell me that I'm going about it all the wrong way. The type of game I'll be writing will probably be similar to Lemmings, in that I need to have support for lots of (fairly small) sprites. Having 30 separate sprites on screen and moving is not too much to ask. (It may be too much to program, but...) But they'll generally be 32x32 pixels or smaller, with room for a few larger ones. I'll write this game to fill the 12" monitor -- 512x384 pixels. It will only support color, probably require System 7, etc. And it uses "direct-screen" drawing; filling the video RAM with bytes for instant gratification. First question: will direct-screen animation work on the PowerPC, if the loosely-defined "correct" way of doing it is followed? From what I have heard and seen of the PowerPC, it doesn't seem like there's any inhibiting factors against using direct-screen graphics. But I haven't gotten my hands on a PPC compiler yet to try it out. Ok. So, here's how I'll do my animation: I'll have two buffers (at about 384k each -- this game will probably require at least 2 megs) the size of the game area. One of these buffers contains the background. The other buffer is a "work" buffer. First I copy the entire background to the work buffer. Then I mask or draw all of my sprites on top of the background in the work buffer. Then I copy the work buffer to the screen. The process continues for each frame of animation. I'll sync the drawing with the electron beam, if necessary. From previous discussions here and elsewhere, this seems to be an accepted method that will result in flicker-free animation. It's memory- intensive, but as I have described it, relatively easy to implement. But (at least) two things bother me: there's two copies of 512x384 bytes occurring for each frame of animation: first the copy of the background into the work buffer, then the copy of the work buffer to the screen. Not to mention all the copies of the sprites -- possibly up to 30. I know there are probably ways to prevent copying the entire screen, and I could use some suggestions. I could keep track of a "dirty rectangle" that needs updating, but for my game I'll have sprites all over the screen so it seems like I'll need to copy the whole screen anyway. Keeping a list of rectangles needing to be copied is another possibility, but this will result in a lot of overhead and required computations, and numerous little copies that would probably make it slower. I did some (rough) experimentation. I took two sprites, each 512x384, and blasted them to the screen in alternating order for 30 seconds, incrementing a counter with each blast. I did this on a Macintosh IIfx. Here are the results: No optimizations: 356 frames / 30 seconds or 11.87 frames/s Compiled for 68020 and up, with all Symantec C++ opts: 554 frames / 30 seconds or 18.47 frames/s Comments: I used the Symantec C++ compiler. And keep in mind I'll have at least two full copies going on for each frame, plus all the work involved in drawing the numerous sprites, overhead from the rest of the game's I/O and logic, etc. I don't think a bad prediction would be that with those results, I might end up with around 6 frames per second. Isn't that pretty bad? For arcade games, how many "complete" screen updates / s are there usually? (I've also got to remind myself that I'm developing this on a IIfx -- which (for now) is still speedier than the average Mac.) Here's the code I use for blasting the 512x384 sprite to the screen: void Sprite::Plot(long x, long y) { long *longPtr, *longPtr2; register long xx; register long yy; long sum1, sum2; if (data_allocated == 1) { HLock(theData); longPtr2 = (long *)(*theData); sum1 = y + height; sum2 = x + width; for (yy=y; yyline_ptr[yy]); for (xx=x; xxFrom john_werner@taligent.com (John Werner) Date: Mon, 28 Feb 1994 03:18:49 GMT Organization: Taligent, Inc. In article <1994Feb27.234911.14595@afterlife.ncsc.mil>, mssmith@afterlife.ncsc.mil (M. Scott Smith) wrote: > But (at least) two things bother me: there's two copies of 512x384 bytes > occurring for each frame of animation: first the copy of the background > into the work buffer, then the copy of the work buffer to the screen. Not > to mention all the copies of the sprites -- possibly up to 30. You're right. This will be too slow, as your experiment below shows. > Keeping a > list of rectangles needing to be copied is another possibility, but this > will result in a lot of overhead and required computations, This is probably the way to do it. If you try hard enough you can optimize the list of rectangles by merging ones that overlap or are adjacent. To make things more complicated, you need to do this all twice: once for copying from your background bitmap to the work buffer, then for the copy from the work buffer to the screen. When copying from the background, you only need to copy the areas corresponding to the sprites' old locations (to erase them). When copying to the screen, you need the union of the old and new sprite locations, to erase the old sprites and draw the new ones. Another strategy would be to divide the screen up into an even grid of rectangles. If a rectangle contains any sprites then it gets copied; otherwise it doesn't. This would work best if you know your sprites are usually going to be concentrated in certain areas rather than randomly scattered around the screen. > and numerous little copies that would probably make it slower. You should test this before you assume it's true. If the bit depths and color tables all match, most of the time is going to be spent writing bits to the screen. Other tips: Make sure all of your bitmaps are longword-aligned. Make sure all the color tables and bit depths match. CopyBits can slow down a lot when they don't. With a custom blitter life will be a lot simpler if you don't have to worry about such things. Expand the left and right edges of areas to be copied so that they end on byte (or word, or longword) boundaries, so CopyBits or your custom blitter has a much simpler job to do. > I don't think a bad prediction would be that > with those results, I might end up with around 6 frames per second. Isn't > that pretty bad? Yes. You need 20 fps or so to look at all decent. 30 would be even better. -- John Werner john_werner@taligent.com Taligent, Inc. +++++++++++++++++++++++++++ >From Turly.OConnor@isltd.insignia.com (Turly OConnor) Date: 28 Feb 1994 10:39:45 -0600 Organization: UTexas Mail-to-News Gateway M. Scott Smith had a few questions regarding speeding up his sprite drawer. Here's one: - Don't bother with locking and unlocking the handle! Since you don't call anything which moves memory, there's no point. The trap dispatcher overhead is likely to be bigger than your entire sprite copying loop! - Re-organise your code so you use do { *longPtr++ = *spritePtr++; } while (--xx); instead of the for(;;) loop you've currently got. - If you know the sprites are 32 pixels wide, unroll your x-loop so that you write all 32 pixels at once; in fact, get rid of your x-loop altogether. Oops, sorry, more than one but what the heck! Have fun! --turly +++++++++++++++++++++++++++ >From al@crucible.powertools.com (Al Evans) Date: 28 Feb 94 16:51:00 GMT Organization: PowerTools, Austin, Texas In article <1994Feb27.234911.14595@afterlife.ncsc.mil> mssmith@afterlife.ncsc.mil (M. Scott Smith) writes: [Sprite animation, wants to support up to 30 32X32 sprites] > First question: will direct-screen animation work on the PowerPC, if >the loosely-defined "correct" way of doing it is followed? From what I >have heard and seen of the PowerPC, it doesn't seem like there's any >inhibiting factors against using direct-screen graphics. But I haven't >gotten my hands on a PPC compiler yet to try it out. Consider the possibility that you may be working on the wrong thing. First, it's difficult to beat CopyBits by much when you're using srcCopy mode and everything is ligned up right (assuming 8-bit color with value of ctSeed equal in offscreen GWorld and onscreen device). Second, remember that even eliminating the offscreen-to-onscreen copy COMPLETELY will only make you about 30% faster (which may be what you have to do to get the performance you want). Third, remember that CopyBits will always be supported and will work on all Macs. [Description of animation loop: offscreen-to-offscreen copy of entire background, offscreen-to-offscreen to sprites, offscreen-to- onscreen of composite] > I know there are probably ways to prevent copying the entire screen, >and I could use some suggestions. I could keep track of a "dirty rectangle" >that needs updating, but for my game I'll have sprites all over the screen >so it seems like I'll need to copy the whole screen anyway. Keeping a >list of rectangles needing to be copied is another possibility, but this >will result in a lot of overhead and required computations, and numerous >little copies that would probably make it slower. My tests indicate that the overhead of maintaining a sorted list of update Rects is small compared to the time saved in copying. Look at it this way: if you only save 4 pixels at each side of the window, that's 4 * 384 * 2 bytes that don't have to be moved, or enough bytes for 3 32X32X8 sprites. [timing tests] >I might end up with around 6 frames per second. Isn't >that pretty bad? For arcade games, how many "complete" screen updates / s >are there usually? (I've also got to remind myself that I'm developing >this on a IIfx -- which (for now) is still speedier than the average Mac.) I've done some pretty extensive speed testing lately in finishing up my Graphic Elements system (watch this space for announcements Real Soon Now). I use a somewhat similar double buffering technique. I find that I can get 8 frames/second on a Mac IIsi with 30 32X32 sprites scattered over the screen and moving randomly. This drops to 7 fps with a "load", i.e. collision processing. On a Quadra 800, the numbers are 33 and 29, respectively. I do not believe that these numbers can be substantially improved without going to a different animation scheme (but I'd love to be proved wrong:-). [...] > Well, I guess that's about it. For the type of game I've described, >am I approaching this in the correct manner? If not, what other techniques >should I try? If so, how can I approach it more efficiently? I'm >looking for speed. I'm not sure if I've found it yet. "Correct" is a big word, but you're approaching it in the only highly general manner (i.e. offscreen construction, off-to-onscreen copy). If I were you, I would look at the following possibilities: 1) Use smaller sprites or fewer of them; 2) Keep a list of dirty Rects and copy only what you have to; 3) Try to "offset" your frame generation so that, for example, only 1/3 of the sprites need updating on a given frame (of course this only works in conjunction with 2). --Al Evans-- -- Al Evans Tu causes, tu causes al@crucible.powertools.com C'est tout ce que tu sais faire cs.utexas.edu!crucible!al -- LaVerdure +++++++++++++++++++++++++++ >From mxmora@unix.sri.com (Matt Mora) Date: 28 Feb 1994 09:33:03 -0800 Organization: SRI International, Menlo Park, CA In article <1994Feb27.234911.14595@afterlife.ncsc.mil> mssmith@afterlife.ncsc.mil (M. Scott Smith) writes: > I know there are probably ways to prevent copying the entire screen, >and I could use some suggestions. I could keep track of a "dirty rectangle" >that needs updating, but for my game I'll have sprites all over the screen >so it seems like I'll need to copy the whole screen anyway. Keeping a >list of rectangles needing to be copied is another possibility, but this >will result in a lot of overhead and required computations, and numerous >little copies that would probably make it slower. You get lots of suggestions about optimizations but one thing you should remember, try any move as little bytes as possible. You will never be able to an entire screen in one tick on apples current hardware. Maybe this will be possible in PowerPC and we will finally be able to play games with a scrolling background. :-) If you have many sprites union their rects and copy that data. Though you are copying more data than you need to you should win by being able to move longwords at a time. Xavier -- ___________________________________________________________ Matthew Xavier Mora Matt_Mora@qm.sri.com SRI International mxmora@unix.sri.com 333 Ravenswood Ave Menlo Park, CA. 94025 +++++++++++++++++++++++++++ >From Arsenault_C@msm.cdx.mot.com (Chris Arsenault) Date: Mon, 28 Feb 1994 13:26:21 -0500 Organization: Motorola Codex In article <1994Feb27.234911.14595@afterlife.ncsc.mil>, mssmith@afterlife.ncsc.mil (M. Scott Smith) wrote: > The type of game I'll be writing will probably be similar to Lemmings, > in that I need to have support for lots of (fairly small) sprites. Having > 30 separate sprites on screen and moving is not too much to ask. (It may > be too much to program, but...) But they'll generally be 32x32 pixels or > smaller, with room for a few larger ones. I'll write this game to fill > the 12" monitor -- 512x384 pixels. It will only support color, probably > require System 7, etc. And it uses "direct-screen" drawing; filling the > video RAM with bytes for instant gratification. > Well, I guess that's about it. For the type of game I've described, > am I approaching this in the correct manner? If not, what other techniques > should I try? If so, how can I approach it more efficiently? I'm > looking for speed. I'm not sure if I've found it yet. Some comments: - if you have a lot of sprites moving on screen then it may be better to optimize the background copy operation between your saved background and your work buffer (the one you do a CopyBits to the screen with). You can unroll a loop in assembler and refresh your work buffer real fast. Then you can do all the real drawing in your work buffer. Given your type of game you have to determine if the overhead of tracking and updating invalid rects is worth the time. Generally the more smaller rects you need to update, the easier it is to save time by just doing a real fast copy of the buffer. I would calculate a dirty rect for all sprites drawn in the work buffer though, so what I actually have to copy to the screen would remain the minimal update rect. (Don't forget to adjust this update rect to the proper multiple of 32 for both left and right edges!) Once calculated, you use this rect to restore the background on the next pass! - You really don't want to play with direct screen drawing for this style of animation for a couple of reasons: Directly writing to the video memory can get you clobbered by some graphics accellerators. If you allow the user to switch out to the Finder and s/he changes the depth of the monitor on the fly, and you don't check it, you're in ds trouble. Also, although you can sync up to obtain a nice smooth animation with vertical blanking you still can end up trying to beat the electron gun. If, in drawing directly to video memory, you end up drawing the last item in your sprite drawlist near the top of the screen when the vertical blanking interval is over, you'll end up with a tearing effect. There is overhead in trying to order sprites, both for front-back and top-bottom drawing (to provide tear-free animation). Also, given you may have a higher refresh rate on some monitors, you'd be playing with an unknown. (Spend more of your development time trying to avoid hardware related issues - you'll thank me later! ;-) ) - I'm assuming that you're going to look through your GDeviceList and set up your VBL task in the correct slot to synch with the monitor or monitors. Again, be aware of different refresh rates for monitors. - Sometimes you don't need a high frame rate to achieve the appearence of a very fast frame rate. For example if you attain 30fps moving your sprites 1 pixel position on the screen you can achieve the same "look" by moving your sprites 2 pixel positions for only 15 fps. AND... if you're tearing at 30fs, but tear-free at 15 fps...the user will prefer the smooth look vs the choppy. - Do everything in your offscreen buffer then use CopyBits to move the dirtyRect to screen...even if CopyBits has to make the transition to different bit depths, chances are it will stay ahead of the electron gun and you'll still get robust, smooth flicker-free animation and your game will have a nice long life. (See Inside Mac III, p20. Although the values are off, the ideas are still valid!) - The only time direct screen drawing is really affordable (or necessary) is when you're doing extremely minimal updates to an existing image using polygons and the like or performing a non-rectangular copy (for example doing a custom block copy that skews the image to some arbitrary angle.) (Rule of thumb - if you have a lot of game event overhead time, like network games or computing intelligence for chars, then simplify the graphics to absolute minimum - most successful with poly or solid color updates) Sounds like your sprites do internal animation - if this is the case you have to do complete draw of the new sprite each pass anyway. Also it might be nicer to concentrate on supporting B&W versions if possible...in terms of market there is still a lot of B&W Mac's out there...including a lot of new PowerBooks. BTW - in Sprite::Plot, you can increase the speed considerably by unrolling the loop (for every iteration of the loop code overhead try to copy as many longwords as you can!) Good luck and put me on your beta test list! Chris -- #include #define AnnoyThem "This bug's for you!" +++++++++++++++++++++++++++ >From u9119523@sys.uea.ac.uk (Graham Cox) Date: Tue, 1 Mar 1994 18:22:04 GMT Organization: School of Information Systems, UEA, Norwich In article <1994Feb27.234911.14595@afterlife.ncsc.mil>, mssmith@afterlife.ncsc.mil (M. Scott Smith) wrote: > Ramble alert! (This one's kinda long..) > > Hi gang! > > I found a few minutes this weekend to revisit my much-procrastinated > tour into the development of Mac arcade games.. (Well, I haven't really > procrastinated, I just haven't had the time. :( > > I've been developing a direct-screen animation toolkit which I'll > (eventually) be using to write games. I'm now working on the "animation > engine" -- the heart of the game where all of the animation will be > performed. > [deleted] > > - M. Scott Smith [mssmith@afterlife.ncsc.mil || umsmith@mcs.drexel.edu] > > Macintosh developer, student, ski bum. Eater of Kellogg's Frosted Flakes. > > "Last chance for fuel on information highway." If you're the type who likes to reinvent the wheel, (like we all are at times!) then go ahead and don't let me stop you. BUT- this has already been done- "SpriteWorld" (archive sites) works identically to the way you describe, with a pair of offscreen work areas. It generates sprites from PICT or cicn resources, and uses the time manager to give sub-tick accuracy. It also has hooks for writing custom blitting routines, and comes with one for 8-bit colour direct screen blitting, or can use CopyBits. The example program turned in something like 100 frames/sec on a Centris 610 animating 5 or 6 50 x 50 pixel sprites. I got 64 frames/sec on my IIsi! It also has full layer support and collision detection. It is stable and easy to use- I rolled it into one of my C applications in one evening and never had the slightest trouble compiling it. Now I have SpriteWorld, I am never going to write another sprite-animation routine again! I would also say that I have nothing whatsoever to do with its author, but I am one very satisfied "customer" -and word-of-mouth advertising is the best kind! A technical point- SpriteWorld uses linked lists to store the data for each sprite, not arrays. I wonder which method is faster? I reckon that the performance is not bound by this anyway, but on the number of pixels blitted per frame. SpriteWorld seems to go to a lot of trouble to minimise the number of pixels blitted per frame, adding a little code overhead to check this, but its high performance seems to suggest that this is a good strategy. - ------------------------------------------------------------------------ Love & BSWK, Graham -Everyone is entitled to their opinion, no matter how wrong they may be... - ------------------------------------------------------------------------ +++++++++++++++++++++++++++ >From Tony Myles Date: 1 Mar 1994 22:55:29 GMT Organization: The 3DO Company In article Graham Cox, u9119523@sys.uea.ac.uk writes: >If you're the type who likes to reinvent the wheel, (like we all are at >times!) then go ahead and don't let me stop you. > >BUT- this has already been done- "SpriteWorld" (archive sites) works >identically to the way you describe, with a pair of offscreen work areas. >It generates sprites from PICT or cicn resources, and uses the time manager >to give sub-tick accuracy. It also has hooks for writing custom blitting >routines, and comes with one for 8-bit colour direct screen blitting, or >can use CopyBits. The example program turned in something like 100 >frames/sec on a Centris 610 animating 5 or 6 50 x 50 pixel sprites. I got >64 frames/sec on my IIsi! It also has full layer support and collision >detection. It is stable and easy to use- I rolled it into one of my C >applications in one evening and never had the slightest trouble compiling >it. There will be a new version of SpriteWorld out soon. I have sped it up about 20-30% using the custom blitter, and about 20% more on top of that using compiled sprites. Numerous bug fixes were rolled in as well. >Now I have SpriteWorld, I am never going to write another sprite-animation >routine again! > >I would also say that I have nothing whatsoever to do with its author, but >I am one very satisfied "customer" -and word-of-mouth advertising is the >best kind! Thanks, this is good to hear. Any chance of a SpriteWorld based version of Desk Invaders? >A technical point- SpriteWorld uses linked lists to store the data for each >sprite, not arrays. I wonder which method is faster? I reckon that the >performance is not bound by this anyway, but on the number of pixels >blitted per frame. SpriteWorld seems to go to a lot of trouble to minimise >the number of pixels blitted per frame, adding a little code overhead to >check this, but its high performance seems to suggest that this is a good >strategy. Early versions of SpriteWorld used arrays, when I switched to doubly linked lists it made no difference (for better or worse) in terms of speed but it did greatly increase flexibility. As far as code overhead goes, I have found that almost anything you can do to reduce the number of pixels you have to move, results in a faster frame rate. During the development of SpriteWorld this has proved true in almost all cases. However, when optimizing any algorithm, you have to keep in mind the most common case. Take for example the case of overlapping sprites. You might go to a lot of trouble to avoid blitting the overlapping areas of the screen more than once per frame, but if your sprites don't overlap much (or at all) this doesn't make sense. The overhead of calculating the difference of the overlapping rects would just slow down the most common case. For something like SpriteWorld, this is particularly tricky, since I don't know for sure what the most common case will be. Indeed, there is a danger of optimizing for the most common case too much, to where the code is no longer good for anything BUT the most common case (which may be OK, again depending on the application). Inevitably it becomes a question of a tradeoffs between application specific optimizations, and code generality and reusability. ...Tony - --------------------------------------------- Tony Myles work: tony.myles@3do.com The 3DO Company home: suiryu@aol.com +++++++++++++++++++++++++++ >From deweeset@ptolemy1.rdrc.rpi.edu (Thomas E. DeWeese) Date: 1 Mar 1994 20:52:02 GMT Organization: Rensselaer Polytechnic Institute, Troy NY, USA In article <1994Feb27.234911.14595@afterlife.ncsc.mil>, M. Scott Smith wrote: >Ramble alert! (This one's kinda long..) > I've been developing a direct-screen animation toolkit which I'll >(eventually) be using to write games. I'm now working on the "animation >engine" -- the heart of the game where all of the animation will be >performed. > The type of game I'll be writing will probably be similar to Lemmings, >in that I need to have support for lots of (fairly small) sprites. Having >30 separate sprites on screen and moving is not too much to ask. (It may >be too much to program, but...) But they'll generally be 32x32 pixels or >smaller, with room for a few larger ones. I'll write this game to fill >the 12" monitor -- 512x384 pixels. It will only support color, probably >require System 7, etc. And it uses "direct-screen" drawing; filling the >video RAM with bytes for instant gratification. Just a note, 30 32x32 sprites in a 512x384 window is pretty crowded (in my opinion). > But (at least) two things bother me: there's two copies of 512x384 bytes >occurring for each frame of animation: first the copy of the background >into the work buffer, then the copy of the work buffer to the screen. Not >to mention all the copies of the sprites -- possibly up to 30. Yes this is a problem. I strongly suggest the 'dirty' rectangle solution propsed by so many others. Using an insertion sort to order them top to bottom, left to right shouldn't be so bad, for only 30-60 elems. >game's I/O and logic, etc. I don't think a bad prediction would be that >with those results, I might end up with around 6 frames per second. Isn't >that pretty bad? Yes, as others have noted 20-30fps is where you want to be. As for your code: Keep your pixmap locked down, actually it doesn't matter too much for this function since you can't cause a handle to move. Don't mess up a nice tight function with stuff like: if (data_allocated == 1) Test it once before you start blitting. This should give you a pretty good starting place to start optomizing your asm. The following is off the top of my head so it might not compile. long rowBytesDiv4; /* row bytes divided by 4 (or >> 2 if your smart) */ void Sprite::Plot(register long x, register long y) { register long *longPtr, *longPtr2; register long *endLn, *endImg; register long rowOffset = rowBytesDiv4 - width; /* possibly precomputed */ longPtr2 = (long *)(*theData); endImg = longPtr2+width*height; longPtr = (long *)(x + theScreen->line_ptr[y]); while (longPtr2 (How would CopyBits compare?) CopyBits has a fair amount of over head so for small blits it loses (it needs to check colorTables, bit depths, clipRgns, and all that junk) But once it get's going you won't be able to beat it. So for large general area copies you can only hope to match it's speed. But for small known size areas you can cream it. BTW the above code won't get you any closer to animating 512x384 at 30fps (if it did, we'd have Sonic THH on the market by now), it will make it possible to animate your 32x32 icons at a reasonable speed if you use a dirty rectangle scheme. Also don't forget your basic math. If your sprite moves < 13 pixes blit one rectangle that encloses both the new, and old location (45x45 = 2025 pixles, 32x32x2 = 2048 pixels). +-----+ +--------+ |##+-----+ |##### | one larger blit |##|.....| two 32x32 blits |##......| +--|.....| | ......| +-----+ +--------+ There is a trade off in that fixed size blits will be faster, due to loop unrolling etc... than a variable sized loop (so you might try haveing fixed width, and variable height, so the width is unrolled and the height isn't. You might have a function for widths of 32, 36, 40, and 44. You could then have an array of function pointers for dispatching appropriately. -- Thomas DeWeese "If it helps you, just think of people using swear deweeset@rdrc.rpi.edu words as truck drivers on the Information Superhighway" -- Matthias Neeracher +++++++++++++++++++++++++++ >From d88-jwa@mumrik.nada.kth.se (Jon Wätte) Date: 2 Mar 1994 10:40:16 GMT Organization: Royal Institute of Technology, Stockholm, Sweden In <2l09tj$4i9@usenet.rpi.edu> deweeset@ptolemy1.rdrc.rpi.edu (Thomas E. DeWeese) writes: >long rowBytesDiv4; /* row bytes divided by 4 (or >> 2 if your smart) */ >>2 isn't very smart. It has strange semantics (precedence, signed/unsigned etc) as well as is harder to read than a simple /4. If your compiler doesn't generate a fast shift instead of a slow compile, you have MUCH worse optimizations to worry about than hand-coding the shift. -- -- Jon W{tte, h+@nada.kth.se, Mac Hacker Deluxe -- "It was, in fact, cool as all get-out. Fortunately it was a little too late (historically speaking) to be groovy." -- Dennis Pelton +++++++++++++++++++++++++++ >From andrewwelc@aol.com (AndrewWelc) Date: 2 Mar 1994 05:23:04 -0500 Organization: America Online, Inc. >> BUT- this has already been done- "SpriteWorld" (archive sites) works identically to the way you describe, with a pair of offscreen work areas. << Sure -- SpriteWorld is good architecture (if you aren't going to do anything with scrolling backgrounds, etc.), but in terms of raw animation speed, forget it. The custom drawing routine just aren't all that optimized -- I recommend writing your own if you plan to animate a reasonable number of sprites on lower-end machines. For the PowerPC, just use CopyBits(). Andrew +++++++++++++++++++++++++++ >From andrewwelc@aol.com (AndrewWelc) Date: 2 Mar 1994 05:23:07 -0500 Organization: America Online, Inc. >> BUT- this has already been done- "SpriteWorld" (archive sites) works identically to the way you describe, with a pair of offscreen work areas. << Sure -- SpriteWorld is good architecture (if you aren't going to do anything with scrolling backgrounds, etc.), but in terms of raw animation speed, forget it. The custom drawing routine just aren't all that optimized -- I recommend writing your own if you plan to animate a reasonable number of sprites on lower-end machines. For the PowerPC, just use CopyBits(). Andrew +++++++++++++++++++++++++++ >From andrewwelc@aol.com (AndrewWelc) Date: 2 Mar 1994 05:23:08 -0500 Organization: America Online, Inc. >> BUT- this has already been done- "SpriteWorld" (archive sites) works identically to the way you describe, with a pair of offscreen work areas. << Sure -- SpriteWorld is good architecture (if you aren't going to do anything with scrolling backgrounds, etc.), but in terms of raw animation speed, forget it. The custom drawing routine just aren't all that optimized -- I recommend writing your own if you plan to animate a reasonable number of sprites on lower-end machines. For the PowerPC, just use CopyBits(). Andrew +++++++++++++++++++++++++++ >From andrewwelc@aol.com (AndrewWelc) Date: 2 Mar 1994 05:23:05 -0500 Organization: America Online, Inc. >> BUT- this has already been done- "SpriteWorld" (archive sites) works identically to the way you describe, with a pair of offscreen work areas. << Sure -- SpriteWorld is good architecture (if you aren't going to do anything with scrolling backgrounds, etc.), but in terms of raw animation speed, forget it. The custom drawing routine just aren't all that optimized -- I recommend writing your own if you plan to animate a reasonable number of sprites on lower-end machines. For the PowerPC, just use CopyBits(). Andrew +++++++++++++++++++++++++++ >From andrewwelc@aol.com (AndrewWelc) Date: 2 Mar 1994 05:23:16 -0500 Organization: America Online, Inc. >> BUT- this has already been done- "SpriteWorld" (archive sites) works identically to the way you describe, with a pair of offscreen work areas. << Sure -- SpriteWorld is good architecture (if you aren't going to do anything with scrolling backgrounds, etc.), but in terms of raw animation speed, forget it. The custom drawing routine just aren't all that optimized -- I recommend writing your own if you plan to animate a reasonable number of sprites on lower-end machines. For the PowerPC, just use CopyBits(). Andrew +++++++++++++++++++++++++++ >From andrewwelc@aol.com (AndrewWelc) Date: 2 Mar 1994 05:23:18 -0500 Organization: America Online, Inc. >> BUT- this has already been done- "SpriteWorld" (archive sites) works identically to the way you describe, with a pair of offscreen work areas. << Sure -- SpriteWorld is good architecture (if you aren't going to do anything with scrolling backgrounds, etc.), but in terms of raw animation speed, forget it. The custom drawing routine just aren't all that optimized -- I recommend writing your own if you plan to animate a reasonable number of sprites on lower-end machines. For the PowerPC, just use CopyBits(). Andrew +++++++++++++++++++++++++++ >From andrewwelc@aol.com (AndrewWelc) Date: 2 Mar 1994 05:23:12 -0500 Organization: America Online, Inc. >> BUT- this has already been done- "SpriteWorld" (archive sites) works identically to the way you describe, with a pair of offscreen work areas. << Sure -- SpriteWorld is good architecture (if you aren't going to do anything with scrolling backgrounds, etc.), but in terms of raw animation speed, forget it. The custom drawing routine just aren't all that optimized -- I recommend writing your own if you plan to animate a reasonable number of sprites on lower-end machines. For the PowerPC, just use CopyBits(). Andrew +++++++++++++++++++++++++++ >From andrewwelc@aol.com (AndrewWelc) Date: 2 Mar 1994 05:23:13 -0500 Organization: America Online, Inc. >> BUT- this has already been done- "SpriteWorld" (archive sites) works identically to the way you describe, with a pair of offscreen work areas. << Sure -- SpriteWorld is good architecture (if you aren't going to do anything with scrolling backgrounds, etc.), but in terms of raw animation speed, forget it. The custom drawing routine just aren't all that optimized -- I recommend writing your own if you plan to animate a reasonable number of sprites on lower-end machines. For the PowerPC, just use CopyBits(). Andrew +++++++++++++++++++++++++++ >From andrewwelc@aol.com (AndrewWelc) Date: 2 Mar 1994 05:23:15 -0500 Organization: America Online, Inc. >> BUT- this has already been done- "SpriteWorld" (archive sites) works identically to the way you describe, with a pair of offscreen work areas. << Sure -- SpriteWorld is good architecture (if you aren't going to do anything with scrolling backgrounds, etc.), but in terms of raw animation speed, forget it. The custom drawing routine just aren't all that optimized -- I recommend writing your own if you plan to animate a reasonable number of sprites on lower-end machines. For the PowerPC, just use CopyBits(). Andrew +++++++++++++++++++++++++++ >From Tony Myles Date: 2 Mar 1994 18:15:58 GMT Organization: The 3DO Company In article <2l1pe8$ehi@rmg01.prod.aol.net> AndrewWelc, andrewwelc@aol.com writes: >Sure -- SpriteWorld is good architecture (if you aren't going to do anything >with scrolling backgrounds, etc.), but in terms of raw animation speed, forget >it. Forget it? Oooh, that stings. ;-) >The custom drawing routine just aren't all that optimized -- I recommend >writing your own if you plan to animate a reasonable number of sprites on >lower-end machines. So do I. I have improved the blitters in SpriteWorld about 20%, but they were really never intended to be used as is. They more or less serve as examples, so that you can write your own that are more specific to your animation. (ie. assuming 32x32 sprites or whatever). >For the PowerPC, just use CopyBits(). Decide to give up on your PowerPC sprite compiler, Andrew? ...Tony - --------------------------------------------- Tony Myles work: tony.myles@3do.com The 3DO Company home: suiryu@aol.com +++++++++++++++++++++++++++ >From al@crucible.powertools.com (Al Evans) Date: 2 Mar 94 19:15:31 GMT Organization: PowerTools, Austin, Texas In another article in this thread (which has unfortunately expired from my news spool), John Werner (john_werner@taligent.com) suggested a strategy of dividing up the background into a grid of rectangles to limit the amount of drawing that would be required for each update. Since this kind of thing is easy to implement in Graphic Elements (took me 26 lines of code, boast boast), I ran some tests. In these tests, a) the moving graphics were 42 X 42 pixels, and b) the background which was updated in any particular cell was the union of the rects of all changed graphics in that cell. I used two different sets of test conditions. In the first test, the graphics were all in two even lines, moving to the right to the edge of the window, then dropping down half their height and moving to the left. When they hit the bottom of the window, they moved back to the top left corner. Using 16 of these graphics on a Quadra 800, I found that the frame rate varied from 60 to 71 fps when the background was a single cell. This is explained by the fact that when a graphic on the bottom right "dropped off" to the top left, almost the entire background (512 X 384) was included in the update. A few quick tests indicated that the optimum dimensions for the background grid were about 3X the "sprite" size. Dividing the background into 128X128 cells gave me frame rates of 63 to 68 fps -- not as high on the high end because of the increased overhead of processing 12 background elements instead of 1, but better on the low end. The improvement in the "look" of the movement was better than the figures would indicate, since these are average frame rates over 30 seconds. This technique really shone, though, when the graphics were in random motion over the background. For the same 16 graphics, I got an average of 46 fps using the 128X128 cells, as compared to 39 fps using a single background cell. And the difference increased as the number of graphics dropped: 80 fps as compared to 60 with 8 graphics, 175 as compared to 96 with 4. Once again, the "look" was greatly improved. I'm sure that's more than you ever wanted to know. But I've found that it's very difficult to predict the effect of an "improvement" in a high-performance animation system, and thought I'd share these numbers since I'm in a position to do so. --Al Evans-- -- Al Evans Tu causes, tu causes al@crucible.powertools.com C'est tout ce que tu sais faire cs.utexas.edu!crucible!al -- LaVerdure +++++++++++++++++++++++++++ >From mxmora@unix.sri.com (Matt Mora) Date: 2 Mar 1994 13:28:29 -0800 Organization: SRI International, Menlo Park, CA In article <421@crucible.powertools.com> al@crucible.powertools.com (Al Evans) writes: >I'm sure that's more than you ever wanted to know. But I've found >that it's very difficult to predict the effect of an "improvement" >in a high-performance animation system, and thought I'd share these >numbers since I'm in a position to do so. Can you post the code? It would be cool to try it on other macs to see how things differ. Xavier -- ___________________________________________________________ Matthew Xavier Mora Matt_Mora@qm.sri.com SRI International mxmora@unix.sri.com 333 Ravenswood Ave Menlo Park, CA. 94025 +++++++++++++++++++++++++++ >From ua025@freenet.Victoria.BC.CA (Cody Jones) Date: Fri, 4 Mar 1994 10:37:46 GMT Organization: The Victoria Freenet Association (VIFA), Victoria, B.C., Canada I'll just put in my 2 bits... I'm also doing a game w/ direct-screen writing, a fair number of 32x32 sprites, etc... I ONLY use direct writing because I've had it with letting the system do it for me. Besides, my game will have a MOD playing so my code needs all the speed it can get. Anyway, a suggestion: Try and make use of the 68040's MOVE16 command. You might keep an array of flags, one for each row on the screen. If the row is set, update it - the entire row, that is. The MOVE16 will probably be fast enough to compensate for copying what you don't need to on each line: on my Tempest (aka. 660AV) I was able to move over 80 megs/second with it! For a 512x384 screen, you can sure get a decent frame rate with that - well, well over 60 fps. I haven't actually implemented this 'row updating' idea, only a routine to test the MOVE16's speed. Of course this method won't work on 68030's... your program would have to check & call the proper update-routine according to the processor. Cody Jones of Zerius Development ua025@freenet.victoria.bc.ca -- +++++++++++++++++++++++++++ >From andrewwelc@aol.com (AndrewWelc) Date: 4 Mar 1994 10:32:04 -0500 Organization: America Online, Inc. >> I haven't actually implemented this 'row updating' idea, only a routine to test the MOVE16's speed. Of course this method won't work on 68030's... your program would have to check & call the proper update-routine according to the processor. << I'm curious what other nitty gritty write-directly-to-the-screen-in-assmebler game programmers out there (like me) are doing for the PowerPC....? Andrew Welch Ambrosia Software +++++++++++++++++++++++++++ >From Ron_Hunsinger@bmug.org Date: Tue, 01 Mar 1994 15:37:18 PST Organization: BMUG, Inc. M. Scott Smith,mssmith@afterlife.ncsc.mil writes: > But (at least) two things bother me: there's two copies of 512x384 bytes >occurring for each frame of animation: first the copy of the background >into the work buffer, then the copy of the work buffer to the screen. Not >to mention all the copies of the sprites -- possibly up to 30. That worries me too. (I developed a sprite engine on the Plus, and ran into the same kinds of problems you're running into.) > No optimizations:356 frames / 30 seconds or 11.87 frames/s > Compiled for 68020 and up, > with all Symantec C++ opts: 554 frames / 30 seconds or 18.47 frames/s And this is the main problem, in a nutshell. Even on a B/W 512x342 screen, there just isn't time to be copying screen-sized data around. The Plus simply didn't have that kind of horsepower, and if you are running on a faster machine you are probably using color and/or a bigger screen, and the problem is still there. Probably will always be there, because I see no reason for the screenSize:processorPower ratio to change much. > I know there are probably ways to prevent copying the entire screen, >and I could use some suggestions. I could keep track of a "dirty rectangle" >that needs updating, but for my game I'll have sprites all over the screen >so it seems like I'll need to copy the whole screen anyway. Keeping a >list of rectangles needing to be copied is another possibility, but this >will result in a lot of overhead and required computations, and numerous >little copies that would probably make it slower. I used the "dirty rectangle" approach, but NOT by keeping a separate rectangle for each sprite. Remember, you're trying to minimize copying, so you don't want to copy the data twice if two sprites overlap. Instead, I divided the screen into a bunch of rectangular zones, each rectangular and nicely aligned. In my case, I made the zones 16x16 pixels, so that the entire screen was like 32x20 zones. (For an effective screen size of 512x320 pixels, meaning I discarded 22 pixels in the vertical dimension.) Then I kept track of which zones were dirty, using a table of 20 longwords. You might call this the "dirty zone" method. Taking the union of draw lists becomes a snap. (You have to update not only the zones where the sprites are now, but also the zones where they were last time.) Just keep two dirty zone lists: one for the work area, to keep track of which zones differ from the background; and one for the screen, for all the zones that need to be updated from the work area. When I actually copied the data to the screen, I walked the dirty zone table, and copied each dirty zone directly to the screen using 16 consecutive MOVE.W instructions. Remember, I was doing this on a Plus, which had a 16-bit data bus and no cache. (At the time, color and the Mac II were only rumors.) I was able to get 30 frames per second on a Plus, with a few hundred sprites moving on the screen at once. Looked nice. Since the zones get updated in top-to-bottom order, I got no flicker even though I made no effort to synchronize with vertical retrace. If I were to do it again, I would use larger zones, keeping them longword aligned but large enough so that the width of the screen would still not exceed 32 zones. And although writing directly to the screen is faster, I think now I would seriously consider using CopyBits for the final copy. I did not appreciate at the time how fragile direct screen manipulation makes your program. I would probably try to combine horizontally adjacent zones into a single CopyBits call, to minimize CopyBit's setup overhead. -Ron Hunsinger +++++++++++++++++++++++++++ >From mssmith@afterlife.ncsc.mil (M. Scott Smith) Date: Sun, 6 Mar 1994 01:30:05 GMT Organization: The Great Beyond Hi gang! I want to extend a very loud "thank you!" to everyone for their messages concerning speeding up my animation. A week or so ago, I brainstormed out loud about a method for doing smooth animation in a game that might potentially have a lot of small sprites. The easiest method I could think of was to keep two offscreen buffers, one a "background" buffer (always containing the pure background) and another a "work" buffer, where I would copy the background and then stick sprites on. Finally, I would copy from the work buffer to the screen. But my suggested method (while certainly easiest) of copying the entire buffer first from background to work area, and then work area to screen, was, by my own testing, slow on a IIfx in 8-bit. I asked for any suggestions, including whether or not "dirty rectangle" approaches would be faster. I also posted some code and asked for suggestions on optimization. Well, dozens of people responded on the net and in e-mail, and every single comment I received was of great help. First, people made code-level suggestions for squeezing more speed out of my algorithm, and I learned some new optimizing techniques that I'll be using from now on. The general concensus seems to be that the best approach to updating the screen as quick as possible is to use "dirty rectangles" or "dirty zones." In some way, maintain areas which you can flag as "dirty" (meaning they have had activity that requires updating). While I pondered over whether or not this might be slow -- after all, maintaing such a list can require quite a few operations -- people said that it will almost always be less expensive than copying all of the data in an entire screen. And that makes sense to me now. Efficient methods of maintaining such lists were presented. I was reminded that libraries such as SpriteWorld exist and already do much of what I want, but I don't mind "reinventing the wheel" because this is a learning experience for me. (This is the same reason I don't use MacApp or TCL but instead write my own class libraries; I may not do it as well, but I learn how it's done. Maybe that's stubborn, but as a kid I took everything apart to see how it works; I don't like "black boxes." Once I learn how to develop my own class libraries, I'll be happy to use other ones since I'll have an idea of how they were written.) I really like the kind of discussion that has been going on in this thread; it's thought-provoking. It'd be great if it could continue; there's lots of general issues involved in game writing which are a little abstract. - -[fade out, fade in..]--- One of the other things that has been eating at me is the best way to handle "timing." The best method will be to make the animation machine- independent. If a sprite is moving across the screen at a certain speed on the PowerMac's, it should move at the same speed on an LC. This may mean skipping frames in the animation -- or moving the sprite along 4 pixels at a time instead of 2. I've mulled over this one a bit, but haven't come up with anything that I'm particularly thrilled about. Any suggestions? And on another note entirely, say you have some type of "animated background." Such as a flaming torch on the wall of a castle. The flame flickers and throws out dancing light along the wall. But it's always in the background -- it's animated just like sprites, but it doesn't interact with the (foreground) sprites. Something I briefly tried some time ago was putting the code for these types of animations in background tasks. Is this more trouble than it's worth? (Is it better to handle all of the animation in the same place?) Thanks again for all the help.. Scott - - M. Scott Smith (mssmith@afterlife.ncsc.mil || umsmith@mcs.drexel.edu) Macintosh developer. Student. Ski bum. Eater of Ben and Jerry's ice cream. +++++++++++++++++++++++++++ >From ua025@freenet.Victoria.BC.CA (Cody Jones) Date: Sun, 6 Mar 1994 02:26:26 GMT Organization: The Victoria Freenet Association (VIFA), Victoria, B.C., Canada " One of the other things that has been eating at me is the best way to handle "timing." The best method will be to make the animation machine- independent. If a sprite is moving across the screen at a certain speed on the PowerMac's, it should move at the same speed on an LC. This may mean skipping frames in the animation -- or moving the sprite along 4 pixels at a time instead of 2." One way I use is this: Keep track of the last time your update routine was called. When you get to the update again, see how many ticks have passed, and for each one, call your update routine. Thus your rout always gets called 60 times a second... well, kind of. After that you output the frame. This method has the advantage you are looking for. No matter how bad the fps rate, objects always move at the same rate. Cody Jones, Zerius Development ua025@freenet.victoria.bc.ca voltaire@amtsgi.bc.ca -- +++++++++++++++++++++++++++ >From alex@metcalf.demon.co.uk (Alex Metcalf) Date: Sun, 6 Mar 1994 11:48:05 GMT Organization: Demon Internet > > One of the other things that has been eating at me is the best way to > handle "timing." The best method will be to make the animation machine- > independent. If a sprite is moving across the screen at a certain speed > on the PowerMac's, it should move at the same speed on an LC. This may > mean skipping frames in the animation -- or moving the sprite along 4 > pixels at a time instead of 2. > > I've mulled over this one a bit, but haven't come up with anything > that I'm particularly thrilled about. Any suggestions? > > And on another note entirely, say you have some type of "animated > background." Such as a flaming torch on the wall of a castle. The > flame flickers and throws out dancing light along the wall. But it's > always in the background -- it's animated just like sprites, but it > doesn't interact with the (foreground) sprites. > > Something I briefly tried some time ago was putting the code for > these types of animations in background tasks. Is this more trouble > than it's worth? (Is it better to handle all of the animation in the > same place?) > > Thanks again for all the help.. > > Scott In my game, I have a simple loop of game code, and I use quite simple code to determine a standard game speed for all Macs: { long tTicks; tTicks = TickCount (); GameLoop (); while (TickCount () - tTicks < kLoopSpeed); } where kLoopSpeed, on my game, is 2. I know this method isn't all that accurate, but it's good enough for what I'm doing. As for the flickering torches idea... that shouldn't be a problem. Just make the torch a sprite just like the others, but make sure that it's one of the first ones copied across to your work area, before any of your moving sprites are copied. That way, anything that passes "over it" will be copied on top of it, and it will look like the torch is behind your main (moving) sprites. Hope this helps, Alex -- Alex Metcalf, Mac programmer in C, C++, HyperTalk, assembler Internet, AOL, BIX: alex@metcalf.demon.co.uk AppleLink: alex@metcalf.demon.co.uk@internet# CompuServe: INTERNET:alex@metcalf.demon.co.uk Delphi: alex@metcalf.demon.co.uk@inet# FirstClass: alex@metcalf.demon.co.uk,Internet Fax (UK): (0570) 45636 Fax (US / Canada): 011 44 570 45636 +++++++++++++++++++++++++++ >From fixer@faxcsl.dcrt.nih.gov (Chris Gonna' Find Ray Charles Tate) Date: Sun, 6 Mar 1994 20:54:35 GMT Organization: DCRT, NIH, Bethesda, MD In article , alex@metcalf.demon.co.uk (Alex Metcalf) writes: >Someone named Scott writes: (sorry; I lost the attribution!) >> >> One of the other things that has been eating at me is the best way to >> handle "timing." The best method will be to make the animation machine- >> independent. If a sprite is moving across the screen at a certain speed >> on the PowerMac's, it should move at the same speed on an LC. This may >> mean skipping frames in the animation -- or moving the sprite along 4 >> pixels at a time instead of 2. >> >> I've mulled over this one a bit, but haven't come up with anything >> that I'm particularly thrilled about. Any suggestions? > In my game, I have a simple loop of game code, and I use quite simple >code to determine a standard game speed for all Macs: > >{ > long tTicks; > > tTicks = TickCount (); > GameLoop (); > while (TickCount () - tTicks < kLoopSpeed); >} > >where kLoopSpeed, on my game, is 2. I know this method isn't all that >accurate, but it's good enough for what I'm doing. Ack! Phtui! (Sorry; I got a little carried away. :-) This might be reasonable if your animation speed is high, but it *does* have the unfortunate property that it locks up the rest of the machine while waiting for an animation interval to pass. Why not set up a simple Time Manager routine to set a flag somewhere that means 'it's time to draw another animation step?' This is particularly nice in that you can have more than one Time Manager routine that set different flags for different movement rates. That way, you don't need the movement rates to necessarily be integer multiples of some base rate (other than the rate of traversal of the main loop, of course). Also, I *believe* that a Time Manager task doesn't take up any execution time while it's pending - is this right? I was of the impression that a pending Time Manager task is just an entry in the task queue, until such time as the Time Manager decides it's time to call it. If this is the case, then you avoid any 'check to see if it's time yet' overhead. Furthermore (:-), this automatically gives you 'simulated' fixed-point movement speeds - i.e. not integer numbers of pixels per step in any given direction. Not having integer pixels/step speeds goes a looooong way towards making your animation look smooth, especially at lower object movement speeds. (Good luck, by the way! And remember that the Time Manager is your friend!) - -------------------------------------------------------------------------- Christopher Tate | "I hate writing, and I hate statistics, but MSD, Inc. | most of all I hate writing about statistics. | I'd rather go to the dentist; at least there fixer@faxcsl.dcrt.nih.gov | you get to spit." -- Ed Sewell +++++++++++++++++++++++++++ >From alex@metcalf.demon.co.uk (Alex Metcalf) Date: Sun, 6 Mar 1994 23:15:50 GMT Organization: Demon Internet In article <1994Mar6.205435.229@alw.nih.gov>, fixer@faxcsl.dcrt.nih.gov (Chris Gonna' Find Ray Charles Tate) wrote: > In article , alex@metcalf.demon.co.uk (Alex Metcalf) writes: > >Someone named Scott writes: (sorry; I lost the attribution!) > >> > >> One of the other things that has been eating at me is the best way to > >> handle "timing." The best method will be to make the animation machine- > >> independent. If a sprite is moving across the screen at a certain speed > >> on the PowerMac's, it should move at the same speed on an LC. This may > >> mean skipping frames in the animation -- or moving the sprite along 4 > >> pixels at a time instead of 2. > >> > >> I've mulled over this one a bit, but haven't come up with anything > >> that I'm particularly thrilled about. Any suggestions? > > > In my game, I have a simple loop of game code, and I use quite simple > >code to determine a standard game speed for all Macs: > > > >{ > > long tTicks; > > > > tTicks = TickCount (); > > GameLoop (); > > while (TickCount () - tTicks < kLoopSpeed); > >} > > > >where kLoopSpeed, on my game, is 2. I know this method isn't all that > >accurate, but it's good enough for what I'm doing. > > Ack! Phtui! > > (Sorry; I got a little carried away. :-) > > This might be reasonable if your animation speed is high, but it *does* > have the unfortunate property that it locks up the rest of the machine > while waiting for an animation interval to pass. > > Why not set up a simple Time Manager routine to set a flag somewhere > that means 'it's time to draw another animation step?' This is > particularly nice in that you can have more than one Time Manager > routine that set different flags for different movement rates. That > way, you don't need the movement rates to necessarily be integer > multiples of some base rate (other than the rate of traversal of the > main loop, of course). Ack! Phtui! That's all fine and well, but if your game doesn't have an event loop (as most arcade games don't, since it takes too much CPU time for background processing), there's nothing else to do while you're waiting for the next animation interval! But it's a good idea. :-) Alex +++++++++++++++++++++++++++ >From s_heidri@iraul1.ira.uka.de (Dietmar Heidrich) Date: 7 Mar 1994 13:58:31 GMT Organization: University of Karlsruhe, FRG In article , Arsenault_C@msm.cdx.mot.com (Chris Arsenault) writes: |> Some comments: [...] |> - Do everything in your offscreen buffer then use CopyBits to move the |> dirtyRect to screen...even if CopyBits has to make the transition to |> different bit depths, chances are it will stay ahead of the electron gun |> and you'll still get robust, smooth flicker-free animation and your game |> will have a nice long life. (See Inside Mac III, p20. Although the values |> are off, the ideas are still valid!) I am no Mac programmer, but on other platforms you can switch video buffers for games instead of copying everything you already have drawn. Is there no way to do that OS compliant on the Mac ? I think CopyBits() will be too slow for action games if you need to copy 640x480x8bit = 307200 bytes per frame. For 30 frames/s update rate, this yields 9 MB/s transfer rate eaten up only for CopyBits(). Assuming you can transfer 16 bytes via burst (giving 576000 bursts needed) in 20 clock cycles, this means 46% CPU time on a 25 MHz 68040. -- Dietmar Heidrich, Universitaet Karlsruhe, Germany "Die Hoffnung auf den Tod ist das einzige, was mich am Leben erhaelt." +++++++++++++++++++++++++++ >From rmah@panix.com (Robert S. Mah) Date: Tue, 08 Mar 1994 01:29:01 -0500 Organization: One Step Beyond s_heidri@iraul1.ira.uka.de (Dietmar Heidrich) wrote: > I am no Mac programmer, but on other platforms you can switch video buffers > for games instead of copying everything you already have drawn. Is there > no way to do that OS compliant on the Mac ? Nope. > I think CopyBits() will be too slow for action games if you need to copy > 640x480x8bit = 307200 bytes per frame. For 30 frames/s update rate, this > [...] Tell that to those who use CopyBits to write arcade games :-). Seriouslly, it's possible, it's just not easy. Cheers, Rob ________________________________________________________________________ Robert S. Mah One Step Beyond rmah@panix.com +++++++++++++++++++++++++++ >From sigurasg@rhi.hi.is (Sigurdur Asgeirsson) Date: 8 Mar 1994 11:25:16 GMT Organization: University of Iceland In <2lfbu7INN597@iraun1.ira.uka.de> s_heidri@iraul1.ira.uka.de (Dietmar Heidrich) writes: >In article , Arsenault_C@msm.cdx.mot.com (Chris Arsenault) writes: [snip] >I am no Mac programmer, but on other platforms you can switch video buffers >for games instead of copying everything you already have drawn. Is there >no way to do that OS compliant on the Mac ? [snip] There is a well defined way to do this for color-quickdraw capable video devices. The video driver interface includes calls to check how many video pages are available, find their baseaddresses and to switch between video pages. It seems that this feature is little enough used though that newer video cards don't bother to support multiple video pages, even if they have the video RAM needed, the Quadras for instance don't seem to support multiple video pages. -- Sigurdur Asgeirsson | "Well you know, C isn't that hard, void (*(*f[])())() Kambasel 26 | for instance declares f as an array of unspecified 109 Reykjavik, Iceland | size, of pointers to functions that return pointers to sigurasg@rhi.hi.is | functions that return void... I think" +++++++++++++++++++++++++++ >From mgleason@cse.unl.edu (Mike Gleason) Date: 9 Mar 1994 02:09:38 GMT Organization: NCEMRSoft |s_heidri@iraul1.ira.uka.de (Dietmar Heidrich) wrote: |> I am no Mac programmer, but on other platforms you can switch video buffers |> for games instead of copying everything you already have drawn. Is there |> no way to do that OS compliant on the Mac ? |Nope. That's pretty depressing. The Sega Genesis and Commodore Amiga, which use the same damn 68000 in the Mac Plus I use, get phemomenal performance. Ever play Sonic the Hedgehog? That should be able to be done on a mac. Hard to believe... I think the Amiga uses a Screen pointer, which is changeable by the programmer, so that to do very fast screen scrolling, all you need to do is set the screen pointer to something else. It makes no sense to me that you have to re-copy the whole damn screen if all you want to do is scroll the screen downward a pixel. -- ______________________________________________________________________________ mike gleason mgleason@cse.unl.edu NCEMRSoft, baby! +++++++++++++++++++++++++++ >From Arsenault_C@msm.cdx.mot.com (Chris Arsenault) Date: Tue, 08 Mar 1994 12:35:30 -0500 Organization: Motorola Codex In article , alex@metcalf.demon.co.uk (Alex Metcalf) wrote: > That's all fine and well, but if your game doesn't have an event loop > (as most arcade games don't, since it takes too much CPU time for > background processing), there's nothing else to do while you're waiting for > the next animation interval! One of the things I do is to switch in and out of a main event loop. When running time critical game code I stay out of the main event loop, working only with specific keypresses etc. When I see a special key (such as the space bar) I switch in and out of the main event loop where I handle events normally. The nice part about this approach is I have very clean/fast animation without background process relinquish jitters, but I can still handle menus, application switching and the like. BTW, when you're the foreground process you can tell the system that you really want all the time you can by setting the WaitNextEvent sleep parameter to 0. Chris -- #include +++++++++++++++++++++++++++ >From Arsenault_C@msm.cdx.mot.com (Chris Arsenault) Date: Tue, 08 Mar 1994 12:51:42 -0500 Organization: Motorola Codex In article <2lfbu7INN597@iraun1.ira.uka.de>, s_heidri@iraul1.ira.uka.de (Dietmar Heidrich) wrote: > I am no Mac programmer, but on other platforms you can switch video buffers > for games instead of copying everything you already have drawn. Is there > no way to do that OS compliant on the Mac ? I think CopyBits() will be too > slow for action games if you need to copy 640x480x8bit = 307200 bytes per > frame. For 30 frames/s update rate, this yields 9 MB/s transfer rate eaten > up only for CopyBits(). Assuming you can transfer 16 bytes via burst (giving > 576000 bursts needed) in 20 clock cycles, this means 46% CPU time on a 25 MHz > 68040. No. Not when focusing on market share. You're right about video page flipping being CPU intensive. That's why you don't see a lot of Mac video games that do full frame (640x480) flipping and if you do the frames are usually small (ever seen QuickTime movies playing at full speed?). Actually, there is a tradeoff involved. By using CopyBits we gain simplicity in handling numerous video configurations and application longevity. What we lose is speed. We don't have a mode 13h or X. If we draw using Toolbox trap calls to memory on a video card, then we have to run over NuBus. (number of draw calls * (Trap dispatch overhead + NuBus overhead + actual operation) = too expensive). BTW - there are video cards out there that support several frame buffers (GWorlds). But they are more likely to be found in high end publishing systems than in the target game Mac - the LCIII. IMHO, I would love to see hardware supported video DMA. I've worked with the Amiga and it was great to have the blitter and copper. Chris -- #include +++++++++++++++++++++++++++ >From flavius@bga.com (Flavius Goombius) Date: 9 Mar 1994 09:48:54 -0600 Organization: PowerTools, Austin, TX In article <1994Mar6.013005.18429@afterlife.ncsc.mil>, M. Scott Smith wrote: > One of the other things that has been eating at me is the best way to >handle "timing." The best method will be to make the animation machine- >independent. If a sprite is moving across the screen at a certain speed >on the PowerMac's, it should move at the same speed on an LC. This may >mean skipping frames in the animation -- or moving the sprite along 4 >pixels at a time instead of 2. > > I've mulled over this one a bit, but haven't come up with anything >that I'm particularly thrilled about. Any suggestions? Sorry about the funky From: line; this is really Al Evans (al@crucible. powertools.com), posting from an alternate site because my newsfeed has been hosed for the past few days. Anyway: Let's take a simple case. There is an "overall" animation system time. Each sprite has variables which represent its move interval and its last move time. For each frame, you run through the sprite list and update the sprites for which lastMove + moveInterval <= currentTime. At this point, you have three options. First, you can set the sprite's last move time to the current system time. The advantage of this approach is that each frame gets drawn for each sprite. The disadvantage is that, on entry, currentTime can easily be lastMove + (10 * moveInterval), and the extra nine moveIntervals are lost forever. In other words, unless the host system is fast enough that the maximum animation time is less than the minimum move interval, the animation will slow down. The second approach is to do something like while ((lastMove + moveInterval) <= currentTime) { MoveSprite(thisSprite); lastMove = lastMove + moveInterval; } This keeps the sprite movement speeds the same on all systems, but leads to skipped frames (and possible jerky animation) on slower systems. In addition, you must provide some means of "stopping the clock" when you are not animating. For example, if the user holds down a menu so that your animation loop doesn't get called for a few seconds, the sprites will all jump to where they are supposed to be "now" if the clock has continued running. Finally, you can combine the two approaches, setting last move equal to lastMove + moveInterval but only moving once each time through the loop. This assumes that there will be time available at some point for the animation to "catch up" on comparatively slow systems (for example, a series of frames in which most sprites are standing still). With this technique, all sprites will be where they are supposed to be -- eventually. The problem of stopping time while the user holds down a menu (or whatever) remains, only in this case the sprites will "run real fast" to get where they're supposed to be when the user releases the menu. I am not really satisfied with any of these approaches, but the only better one I can think of is to measure system speed and alter the move distances (and frame changes) of each sprite, possibly using fixed-point numbers for fractional pixels. If anybody has a better method, I'd like to hear it. For a variety of reasons, I personally use the first method, and accept the inevitable slowdown on slower systems. --Al Evans-- +++++++++++++++++++++++++++ >From alex@metcalf.demon.co.uk (Alex Metcalf) Date: Wed, 9 Mar 1994 18:26:03 GMT Organization: Demon Internet In article , Arsenault_C@msm.cdx.mot.com (Chris Arsenault) wrote: > In article , > alex@metcalf.demon.co.uk (Alex Metcalf) wrote: > > > That's all fine and well, but if your game doesn't have an event loop > > (as most arcade games don't, since it takes too much CPU time for > > background processing), there's nothing else to do while you're waiting for > > the next animation interval! > > One of the things I do is to switch in and out of a main event loop. When > running time critical game code I stay out of the main event loop, working > only with specific keypresses etc. When I see a special key (such as the > space bar) I switch in and out of the main event loop where I handle events > normally. The nice part about this approach is I have very clean/fast > animation without background process relinquish jitters, but I can still > handle menus, application switching and the like. > > BTW, when you're the foreground process you can tell the system that you > really want all the time you can by setting the WaitNextEvent sleep > parameter to 0. Interesting.... I already have an event loop for other parts of the game (such as loading and intro), but I hadn't considered sharing my important game code time with other events. Worth a try! Alex +++++++++++++++++++++++++++ >From ua025@freenet.Victoria.BC.CA (Cody Jones) Date: Thu, 10 Mar 1994 08:58:39 GMT Organization: The Victoria Freenet Association (VIFA), Victoria, B.C., Canada I posted my method of handling animation-rates on different systems some time ago. Others have posted similar ideas and some think that it would be wise to use Time Manager tasks to handle movement. There is no need - to avoid having movement be integer-multiples of the update-frequency, simply store your velocity and positions as fixed point. In my present project I use 10.6 bits. I have a routine that converts a fixed-pt. coordinate and two lengths into a rectangle; this is used for any memory-copying or intersection-testing. Personally I think doing it this way is better than setting up a Time Manager task for every moving object. Cody Jones Zerius Development -- +++++++++++++++++++++++++++ >From s_heidri@ira.uka.de (Dietmar Heidrich) Date: 10 Mar 1994 18:12:58 GMT Organization: University of Karlsruhe, Comp. Sc. Dept., FRG Chris Arsenault (Arsenault_C@msm.cdx.mot.com) wrote: : In article <2lfbu7INN597@iraun1.ira.uka.de>, s_heidri@iraul1.ira.uka.de : (Dietmar Heidrich) wrote: : > I am no Mac programmer, but on other platforms you can switch video buffers : > for games instead of copying everything you already have drawn. Is there : > no way to do that OS compliant on the Mac ? I think CopyBits() will be too : > slow for action games if you need to copy 640x480x8bit = 307200 bytes per : > frame. For 30 frames/s update rate, this yields 9 MB/s transfer rate eaten : > up only for CopyBits(). Assuming you can transfer 16 bytes via burst (giving : > 576000 bursts needed) in 20 clock cycles, this means 46% CPU time on a 25 MHz : > 68040. : Actually, there is a tradeoff involved. By using CopyBits we gain : simplicity in handling numerous video configurations and application : longevity. What we lose is speed. We don't have a mode 13h or X. If we : draw using Toolbox trap calls to memory on a video card, then we have to : run over NuBus. (number of draw calls * (Trap dispatch overhead + NuBus : overhead + actual operation) = too expensive). What is mode 13h ? I think you assume I am an Intel-Weirdo. I AM NOT ! But you can design hardware-independant systems with double-buffering and OS compliancy. You do not have to lose speed. And as long as the system provides fast BitBlt() for the graphics board memory, the NuBus should not be an obstacle. Dietmar Heidrich +++++++++++++++++++++++++++ >From dwareing@apanix.apana.org.au (David Wareing) Date: 11 Mar 94 04:18:24 GMT Organization: Apanix Public Access Unix, +61 8 373 5485 (5 lines) mgleason@cse.unl.edu (Mike Gleason) writes: >|s_heidri@iraul1.ira.uka.de (Dietmar Heidrich) wrote: >|> I am no Mac programmer, but on other platforms you can switch video buffers >|> for games instead of copying everything you already have drawn. Is there >|> no way to do that OS compliant on the Mac ? >|Nope. >That's pretty depressing. The Sega Genesis and Commodore Amiga, which >use the same damn 68000 in the Mac Plus I use, get phemomenal performance. Yeah, I wonder why. Can you say "custom blitting hardware"? Decent graphic performance is expected from both the Sega Genesis/MegaDrive and the Amiga, as both started out life as games machines (both still are, but I digress). The did not start their lives as multi-purpose home and business computers. They do one job and they do it well. Want to try and run Word or Lotus 123 on a Sega games machine? Of course not - games boxes weren't designed to do such things. Just as the Mac Plus was not designed to play Sonic the Hedgehog. >Ever play Sonic the Hedgehog? That should be able to be done on a mac. >Hard to believe... *Very* hard to believe actually. Why should it be able to done on a mac? Somehow I don't think the number one choice for buying a mac is its ability to play Sonic. I agree that macs should eventually come standard with some form of hardware-accelerated graphics, but lets not get carried away and whine that you can't play Sonic on a lowly Mac Plus. >I think the Amiga uses a Screen pointer, which is >changeable by the programmer, so that to do very fast screen scrolling, >all you need to do is set the screen pointer to something else. It makes >no sense to me that you have to re-copy the whole damn screen if all you >want to do is scroll the screen downward a pixel. See the comments above about the Amiga's blitting hardware. Damn it. Horses for courses. -- David Wareing Adelaide, South Australia Mac Games & Multimedia Programming dwareing@apanix.apana.org.au - -------------------------------------------------------------------- +++++++++++++++++++++++++++ >From snozer@cats.ucsc.edu (Daniel Craig Jalkut) Date: 14 Mar 1994 08:22:55 GMT Organization: University of California, Santa Cruz In dwareing@apanix.apana.org.au (David Wareing) writes: >Yeah, I wonder why. Can you say "custom blitting hardware"? Decent graphic >performance is expected from both the Sega Genesis/MegaDrive and the >Amiga, as both started out life as games machines (both still are, but I >digress). The did not start their lives as multi-purpose home and business >computers. They do one job and they do it well. Want to try and run Word >or Lotus 123 on a Sega games machine? Of course not - games boxes weren't >designed to do such things. Just as the Mac Plus was not designed to play >Sonic the Hedgehog. But the bottom line is that the Amiga can do everything the Mac can do, but the converse is not true. The advantages you point out for the Mac are all software(which is why i'm a mac user and no longer an Amigan), if the software were written as well for the Amiga(including the OS), then you'd have the equivalent of a Macintosh with the bonus of excellent graphics hardware. And the Amiga computers were sold for much less than macs in the past, so it's not infeasable cost-wise that the Macs have this type of hardware for graphics. Would be nice... +++++++++++++++++++++++++++ >From rba26@cas.org (Brad Andrews) Date: Mon, 14 Mar 1994 18:08:22 GMT Organization: Chemical Abstracts Service In article dpi@darkstar.UCSC.EDU, snozer@cats.ucsc.edu (Daniel Craig Jalkut) writes: ] ]But the bottom line is that the Amiga can do everything the Mac can ]do, but the converse is not true. The advantages you point out for Hardly. Certainly you may prefer the Amiga, and many do, but some things are extremely difficult. I had a lot more hastles getting an Amiga version of a game port running than I did on the Mac, including such things as supporting a hard drive. - - Brad Andrews brad.andrews@cas.org All opinions are strictly mine +++++++++++++++++++++++++++ >From snozer@cats.ucsc.edu (Daniel Craig Jalkut) Date: 15 Mar 1994 16:03:41 GMT Organization: University of California, Santa Cruz In <1994Mar14.180822.7882@chemabs.uucp> rba26@cas.org (Brad Andrews) writes: >Hardly. Certainly you may prefer the Amiga, and many do, but some things are >extremely difficult. I had a lot more hastles getting an Amiga version of >a game port running than I did on the Mac, including such things as supporting a >hard drive. If I preferred Amigas, I wouldn't have said that I was a mac person. +++++++++++++++++++++++++++ >From s_heidri@irau32.ira.uka.de (Dietmar Heidrich) Date: 17 Mar 1994 13:36:48 GMT Organization: University of Karlsruhe, FRG In article , dwareing@apanix.apana.org.au (David Wareing) writes: |> mgleason@cse.unl.edu (Mike Gleason) writes: |> |> >|s_heidri@iraul1.ira.uka.de (Dietmar Heidrich) wrote: |> |> >|> I am no Mac programmer, but on other platforms you can switch video buffers |> >|> for games instead of copying everything you already have drawn. Is there |> >|> no way to do that OS compliant on the Mac ? |> |> >|Nope. |> |> >That's pretty depressing. The Sega Genesis and Commodore Amiga, which |> >use the same damn 68000 in the Mac Plus I use, get phemomenal performance. |> |> Yeah, I wonder why. Can you say "custom blitting hardware"? Decent graphic |> performance is expected from both the Sega Genesis/MegaDrive and the |> Amiga, as both started out life as games machines (both still are, but I |> digress). The did not start their lives as multi-purpose home and business |> computers. They do one job and they do it well. Want to try and run Word |> or Lotus 123 on a Sega games machine? Of course not - games boxes weren't |> designed to do such things. Just as the Mac Plus was not designed to play |> Sonic the Hedgehog. I did not ask for special-purpose hardware, I was asking about opening and switching two video buffers. To me, this purely seems to be a question of programming interface. The MacOS does not support this (though it would be quite simple to implement that), so the game programming idea I had is dead. -- Dietmar Heidrich, Universitaet Karlsruhe, Germany "Die Hoffnung auf den Tod ist das einzige, was mich am Leben erhaelt." +++++++++++++++++++++++++++ >From fixer@faxcsl.dcrt.nih.gov (Chris Gonna' Find Ray Charles Tate) Date: Thu, 17 Mar 1994 16:15:36 GMT Organization: DCRT, NIH, Bethesda, MD In article <2m9mdgINNei4@iraun1.ira.uka.de>, s_heidri@irau32.ira.uka.de (Dietmar Heidrich) writes: > >I did not ask for special-purpose hardware, I was asking about opening and >switching two video buffers. To me, this purely seems to be a question of >programming interface. The MacOS does not support this (though it would be >quite simple to implement that), so the game programming idea I had is dead. But video double-buffering *is* dependant on the hardware. Think about it - you need to be able to tell the video card where to look in RAM for its frame buffer. That sounds like hardware functionality to me.... I *believe* the original Apple color video card (that they would sell you with a Mac II) supported two switchable frame buffers in 16-color mode. You switched between them with a Control() call to the video driver, as I recall. I also think that Vette! (or some other driving game?) used this capability. Unfortunately, it's not a guaranteed availability by any stretch of the imagination, and so you can't write code depending on it. I agree that it would be nice to have hardware pan, though, as a documented and required video card capability. That's the one that's the most expensive to do in software. Makes the idea of a 'Xevious' clone pretty remote. :-) - -------------------------------------------------------------------------- Christopher Tate | "I hate writing, and I hate statistics, but MSD, Inc. | most of all I hate writing about statistics. | I'd rather go to the dentist; at least there fixer@faxcsl.dcrt.nih.gov | you get to spit." -- Ed Sewell +++++++++++++++++++++++++++ >From Pascal_Haakmat Date: Mon, 14 Mar 94 20:09:46 +0100 Organization: (none) >That's pretty depressing. The Sega Genesis and Commodore Amiga DW> Horses for courses. Nonetheless, it remains pretty depressing. Pascal. - - Obolus 1.0.2 * Origin: pretty blue dreams (2:281/202.13) --------------------------- >From peirce@outpost.SF-Bay.org (Michael Peirce) Subject: System Folder on NONstartup disk Date: Thu, 3 Mar 94 19:51:03 PST Organization: Peirce Software, Inc. Does anyone know how to find the System Folder on a volume that isn't the startup volume? -- Michael Peirce -- peirce@outpost.sf-bay.org -- Peirce Software, Inc. -- 719 Hibiscus Place, Suite 301 -- -- San Jose, California USA 95117 -- Makers of: Smoothie & -- voice: +1.408.244.6554 fax: +1.408.244.6882 -- Peirce Print Tools -- AppleLink: peirce & America Online: AFC Peirce +++++++++++++++++++++++++++ >From mxmora@unix.sri.com (Matt Mora) Date: 4 Mar 1994 09:42:08 -0800 Organization: SRI International, Menlo Park, CA In article peirce@outpost.SF-Bay.org (Michael Peirce) writes: >Does anyone know how to find the System Folder on a volume that isn't >the startup volume? Are you talking about a volume that has a system folder that's not blessed? If its not blessed you probably need to do a PBCatSearch. If its blessed, but not the startup volume, I assume you call findfolder with the vRefNum set to the vRefnum of the volume that you want to look on. Being that you're Michael Peirce, you probably already tried that it it doesn't work. In that case do scan of the disk and look for a folder that contains the finder and system at the same level and you have a good chance that those files parent directory is/was a system folder. Xavier P.S. Are you setting up another netter's dinner? -- ___________________________________________________________ Matthew Xavier Mora Matt_Mora@qm.sri.com SRI International mxmora@unix.sri.com 333 Ravenswood Ave Menlo Park, CA. 94025 +++++++++++++++++++++++++++ >From Robin J. Lunge Date: 5 Mar 1994 03:36:41 GMT Organization: Cornell University In article Michael Peirce, peirce@outpost.SF-Bay.org writes: >Does anyone know how to find the System Folder on a volume that isn't >the startup volume? FindFolder ought to work on any startup disk -- whether it is the current startup disk or not. If you are talking about a disk that is not blessed, the only solution is to search for a folder containing a "Finder" and a "System" (use PBCatSearch if it is available). The Finder and System strings are script-independent. +++++++++++++++++++++++++++ >From Ron_Hunsinger@bmug.org Date: Sat, 05 Mar 1994 19:39:48 -0700 Organization: BMUG, Inc. Michael Peirce,peirce@outpost.SF-Bay.org writes: >Does anyone know how to find the System Folder on a volume that isn't >the startup volume? Its directoryID is the first longword of vcbFndrInfo. This isn't documented anywhere, but I don't see how they can change it, since the ROM has to be getting the system folder from here at bootup. -Ron Hunsinger +++++++++++++++++++++++++++ >From macguru@halcyon.com. (Allan Foster) Date: 10 Mar 1994 07:08:02 GMT Organization: Guru Inc In article <1994Mar05.193948.1193292@bmug.org> Ron_Hunsinger@bmug.org writes: > Michael Peirce,peirce@outpost.SF-Bay.org writes: > > >Does anyone know how to find the System Folder on a volume that isn't > >the startup volume? > > Its directoryID is the first longword of vcbFndrInfo. This isn't > documented anywhere, but I don't see how they can change it, since > the ROM has to be getting the system folder from here at bootup. > Except that I do not believe that the rom gets this information... That is all done by the boot blocks... just my $0.02 nitpicking! Allan Foster - -------------------------------------------------------- I am responsible for what I say and do. -- Allan Foster -- --------------------------- >From "Andrew C. Plotkin" Subject: Trap dispatcher overhead Date: Tue, 1 Mar 1994 19:23:18 -0500 Organization: Information Technology Center, Carnegie Mellon, Pittsburgh, PA Every few days, a post floats by here saying "Don't call toolbox traps in time-critical loops; they take forever." How long is forever? I mean, is there a nice rule like "a trap dispatch is worth 27 pointer dereferences on a '030 CPU"? What about "idiot" toolbox calls (like SetRectSize or OffsetRect, that would be blindingly fast if compiled inline)? Is is worth #defining macros to replace them, or do the header files take care of this? (I'd look, but I'm not at my Mac right now.) (Think C 5.0.4 header files, if it matters.) And, most importantly :-) why doesn't Inside Macintosh tell you about this? I originally assumed that a toolbox call was as fast as any other function call, with maybe a couple of memory lookups and register loads tacked on. --Z "And Aholibamah bare Jeush, and Jaalam, and Korah: these were the borogoves..." +++++++++++++++++++++++++++ >From resnick@cogsci.uiuc.edu (Pete Resnick) Date: Wed, 02 Mar 1994 00:09:17 -0600 Organization: University of Illinois at Urbana-Champaign In article , "Andrew C. Plotkin" wrote: >Every few days, a post floats by here saying "Don't call toolbox traps >in time-critical loops; they take forever." How long is forever? I mean, >is there a nice rule like "a trap dispatch is worth 27 pointer >dereferences on a '030 CPU"? Examples: On the original 68000, the trap itself takes 34 clock cycles. On the 68030, it takes 18-20 cycles. The trap dispatcher takes some amount of time to figure out what routine to call for an individual trap word, so you would have to add on the time it takes to go through a small search. Then the RTE is 20 cycles on the 68000, or 18-20 cycles on the 68030. So altogether, we're probably talking about something on the order of a divide instruction. That's a good chunk of overhead for silly things like SetRect, but not bad at all for other things. pr -- Pete Resnick (...so what is a mojo, and why would one be rising?) Graduate assistant - Philosophy Department, Gregory Hall, UIUC System manager - Cognitive Science Group, Beckman Institute, UIUC Internet: resnick@cogsci.uiuc.edu +++++++++++++++++++++++++++ >From ari@world.std.com (Ari I Halberstadt) Date: Sat, 5 Mar 1994 11:11:29 GMT Organization: The World Public Access UNIX, Brookline, MA In article , Andrew C. Plotkin wrote: >Every few days, a post floats by here saying "Don't call toolbox traps >in time-critical loops; they take forever." How long is forever? I mean, >is there a nice rule like "a trap dispatch is worth 27 pointer >dereferences on a '030 CPU"? If speed of execution is truly critical then you're better off not using a Toolbox trap. For instance, context switches for threads should be very efficient. In my Thread Library (a publicly available implementation of nonpreemptive threads), threads are scheduled for execution at a certain time. I wanted to reduce the time spent in context switches, and since the scheduling loop was already pretty minimal I substituted the use of the TickCount trap with a direct access to the Ticks low-memory global. This resulted in nearly a 50% decrease in the time spent in scheduling context switches. Apple's Thread Manager is slower than Thread Library. I suspect that, at least in part, the slowness of Apple's Thread Manager is due to its use of traps. You should, however, take great pains to use documented traps to access the operating system. Before using the Ticks low-memory global, I tried calling the TickCount trap only once. Instead of something like the following: for (each thread) { if (TickCount() - thread->went_to_sleep >= thread->sleep_time) activate this thread; } you could cache the value of TickCount, assuming the inner loop would execute in less than 1 tick (a valid assumption for many operations). unsigned long ticks; ticks = TickCount(); for (each thread) { if (ticks >= thread->time_to_wakeup) // we precalculated time_to_wakeup activate this thread; } Only if this is not feasible (because the loop takes too long), or is still too slow, should you use the Ticks low-memory global. -- Ari Halberstadt ari@world.std.com #include "These beetles were long considered to be very rare because very few entomologists look for beetles in the mountains, in winter, at night, during snow storms." -- Purves W. K., et al, "Life: The Science of +++++++++++++++++++++++++++ >From "Andrew C. Plotkin" Date: Wed, 9 Mar 1994 11:45:19 -0500 Organization: Information Technology Center, Carnegie Mellon, Pittsburgh, PA In article , Andrew C. Plotkin wrote: >Every few days, a post floats by here saying "Don't call toolbox traps >in time-critical loops; they take forever." How long is forever? I mean, >is there a nice rule like "a trap dispatch is worth 27 pointer >dereferences on a '030 CPU"? A small experiment (what, facts on the Net?) has determined that calling the SetRect trap takes about -four times- the time of the equivalent four assignment statements. Parameters: '040 CPU, Centris 610 virtual memory off, 32-bit mode off Think C 5.0.4, no optimization A loop which just calls SetRect (or the equivalent macro) 10^n times, same arguments each time, none of the arguments equal to zero. (Yes, I disassembled the code and made sure it wasn't sneakily optimizing anything away behind my back.) The object size difference was a few bytes (four or six, I think), which is unlikely to be a big deal. So I put SetRect and SetPt macros into my project. And immediately it stopped working right. Sigh. Turned out I had two calls of the form SetRect(&box, x, y, x+box.right-box.left, y+box.bottom-box.top); and changing the function call to a macro changed the semantics! Heh. Be warned. Conclusion: it's worthwhile, but be careful. And in C++ you probably want to declare an inline function rather than a macro. --Z "And Aholibamah bare Jeush, and Jaalam, and Korah: these were the borogoves..." +++++++++++++++++++++++++++ >From macguru@halcyon.com. (Allan Foster) Date: 10 Mar 1994 07:12:12 GMT Organization: Guru Inc In article "Andrew C. Plotkin" writes: > In article , > Andrew C. Plotkin wrote: > >Every few days, a post floats by here saying "Don't call toolbox traps > >in time-critical loops; they take forever." How long is forever? I mean, > >is there a nice rule like "a trap dispatch is worth 27 pointer > >dereferences on a '030 CPU"? > > A small experiment (what, facts on the Net?) has determined that calling > the SetRect trap takes about -four times- the time of the equivalent > four assignment statements. > The trap dispatcher overhead is in the order of 120 Cycles, depending on the machine, and which trap you are calling.... I believe that toolbox traps take slightly longer, (140?? cycles) It is a fact that the trivial traps should rather be coded inline. These being SetPt, EqualPt and even the Rect calls should be inline. In fact, I believe that the new MPW glue libraries actually implement some these functions as glue rather than the trap call.... For most other traps, the overhead of the dispatcher becomes insignificant. Allan Foster - -------------------------------------------------------- I am responsible for what I say and do. -- Allan Foster -- +++++++++++++++++++++++++++ >From sigurasg@rhi.hi.is (Sigurdur Asgeirsson) Date: 10 Mar 1994 14:47:33 GMT Organization: University of Iceland In <2lmh8c$5l4@nwfocus.wa.com> macguru@halcyon.com. (Allan Foster) writes: >In article >"Andrew C. Plotkin" writes: >> In article , >> Andrew C. Plotkin wrote: >> >Every few days, a post floats by here saying "Don't call toolbox traps [snip] >> >The trap dispatcher overhead is in the order of 120 Cycles, depending >on the machine, and which trap you are calling.... I believe that >toolbox traps take slightly longer, (140?? cycles) When virtual memory is enabled you get some additional overhead. Basically what happens is that the a-trap traps to supervisory level via the VBR trap vector, then there's a shift back down to user level, and a jump to the original lomem trap vector. I sometimes wonder if this additional a-trap overhead is the main cause for the apparent slowdown when VM is on. -- Sigurdur Asgeirsson | "Well you know, C isn't that hard, void (*(*f[])())() Kambasel 26 | for instance declares f as an array of unspecified 109 Reykjavik, Iceland | size, of pointers to functions that return pointers to sigurasg@rhi.hi.is | functions that return void... I think" +++++++++++++++++++++++++++ >From platypus@cirrus.som.cwru.edu (Gary Kacmarcik) Date: 10 Mar 1994 18:58:48 GMT Organization: Case Western Reserve University, Cleveland, Ohio (USA) In article <2lmh8c$5l4@nwfocus.wa.com> macguru@halcyon.com. (Allan Foster) writes: > In article > "Andrew C. Plotkin" writes: > > > > A small experiment (what, facts on the Net?) has determined that calling > > the SetRect trap takes about -four times- the time of the equivalent > > four assignment statements. > > The trap dispatcher overhead is in the order of 120 Cycles, depending > on the machine, and which trap you are calling.... I believe that > toolbox traps take slightly longer, (140?? cycles) > > It is a fact that the trivial traps should rather be coded inline. > These being SetPt, EqualPt and even the Rect calls should be inline. last night i wrote a program which takes a PEF application as input and modifies the app so that all calls to SetRect and SetPt are made "inline". (well, OK, i had written all of the PEF parsing stuff earlier, i just had to modify it to scan for and modify these routines). it does this by replacing the 6-instruction global linkage for the routine with an implementation of the routine itself. this can be done for any routine that can be implemented in 5 (or fewer) PowerPC instructions. basically, i convert: into: glink: lwz r12,xx(r2) subic r3,r3,2 stw r2,0x14(r1) sthu r5,2(r3) lwz r0,0x0(r12) sthu r4,2(r3) lwz r2,0x4(r12) sthu r7,2(r3) mtctr r0 sthu r6,2(r3) bctr blr i haven't tested it yet (since i don't have a PowerMac), but i see no reason why this shouldn't work. the only "worry" i have is that it trashes r3 (which contains the ptr to the rect), but since SetRect doesn't return a value and r3-r10 are volatile, i believe that this should be OK. anyway, i can't distribute this yet because of licensing issues that i have to work out with Apple. i wrote the code, but it's based on some of Apple's headers -- so i need to make sure that things are OK before i release it. i'll post it somewhere as soon as these issues are resolved. -gary j kacmarcik platypus@curie.ces.cwru.edu +++++++++++++++++++++++++++ >From rollin@newton.apple.com (Keith Rollin) Date: Sun, 13 Mar 1994 01:42:44 GMT Organization: Apple Computer, Inc. In article , "Andrew C. Plotkin" wrote: > In article , > Andrew C. Plotkin wrote: > >Every few days, a post floats by here saying "Don't call toolbox traps > >in time-critical loops; they take forever." How long is forever? I mean, > >is there a nice rule like "a trap dispatch is worth 27 pointer > >dereferences on a '030 CPU"? > > A small experiment (what, facts on the Net?) has determined that calling > the SetRect trap takes about -four times- the time of the equivalent > four assignment statements. > > Parameters: > '040 CPU, Centris 610 > virtual memory off, 32-bit mode off > Think C 5.0.4, no optimization > A loop which just calls SetRect (or the equivalent macro) 10^n times, > same arguments each time, none of the arguments equal to zero. (Yes, I > disassembled the code and made sure it wasn't sneakily optimizing > anything away behind my back.) > > The object size difference was a few bytes (four or six, I think), which > is unlikely to be a big deal. > > So I put SetRect and SetPt macros into my project. And immediately it > stopped working right. Sigh. Turned out I had two calls of the form > SetRect(&box, x, y, x+box.right-box.left, y+box.bottom-box.top); > and changing the function call to a macro changed the semantics! Heh. Be > warned. > > Conclusion: it's worthwhile, but be careful. And in C++ you probably > want to declare an inline function rather than a macro. And after you started using the macros, was there any discernable difference in the execution speed of your program? Was there any measurable difference in the speed of your program? I want to thank you for actually performing the experiment and seeing what the effect of the trap dispatcher has on small functions like SetRect and SetPt. But before a "ban calling through the trap dispatcher" campaign gets started, I want to highlight two things: 1) The overhead of the trap dispatcher is negligable for most calls. For instance, it would be interesting to see what measurable difference there is in calling LineTo via the trap dispatcher and calling it directly (after a GetTrapAddress call). 2) Even when there is a measurable difference, is there an _apparent_ difference? Is it worth the hassle and compatibility problems of re-implementing system functionality inline or calling a system function directly? - -------------------------------------------------------------------------- Keith Rollin --- Phantom Programmer --- Apple Computer, Inc. --- Team Newton +++++++++++++++++++++++++++ >From mxmora@unix.sri.com (Matt Mora) Date: 16 Mar 1994 16:32:25 -0800 Organization: SRI International, Menlo Park, CA In article rollin@newton.apple.com (Keith Rollin) writes: >2) Even when there is a measurable difference, is there an _apparent_ >difference? Is it worth the hassle and compatibility problems of >re-implementing system functionality inline or calling a system function >directly? The original thread was about doing his own line drawing by writing directly to screen. If he didn't care about that incompatibility, then calling the trap directly is the lesser of the two evils. If your goal is speed, calling a trap isn't going to help, no matter how small the overhead. Xavier -- ___________________________________________________________ Matthew Xavier Mora Matt_Mora@sri.com SRI International mxmora@unix.sri.com 333 Ravenswood Ave Menlo Park, CA. 94025 --------------------------- >From jclark@galaxy.csc.calpoly.edu (Joseph V Clarke) Subject: User in a menu? Date: Tue, 08 Mar 94 19:16:35 GMT Organization: Computer Science Department, Cal Poly SLO An event is only generated when a menu item has been selected... So how could I find out if the user is clicking on a menu.. (not neccessarily selecting an item, though.) Can I patch some kind of interrupt handler? My application is real time intensive and when someone holds down the menu, my app loses control of the mac and the real time is lost (the data is crunched and when I release the menu, it gushes out...thereby not accurately representing the data.) I would just like to clear the buffer and eliminate the data if the user happened to be in the menu for awhile. Suggestions? Thanks for your time! Joseph -- Telemidi - A Mac application that allows 2 musicians to instantaneously express their musical ideas in real time over the phone lines. Joseph V. Clarke ===================================== jclark@galaxy.calpoly.edu +++++++++++++++++++++++++++ >From sw@network-analysis-ltd.co.uk (Sak Wathanasin) Date: Wed, 9 Mar 94 19:52:17 GMT Organization: Network Analysis Ltd In article <1994Mar08.191635.25383@rat.csc.calpoly.edu> (comp.sys.mac.programmer), jclark@galaxy.csc.calpoly.edu (Joseph V Clarke) writes: > some kind of interrupt handler? My application is real time > intensive and when someone holds down the menu, my app loses control > of the mac and the real time is lost (the data is crunched and when > I release the menu, it gushes out...thereby not accurately representing > the data.) > > I would just like to clear the buffer and eliminate the data if the > user happened to be in the menu for awhile. Suggestions? Try using a MenuHook proc: see Inside Mac vol 1 pg 356. Sak Wathanasin Network Analysis Limited 178 Wainbody Ave South, Coventry CV3 6BX, UK Internet: sw@network-analysis-ltd.co.uk uucp: ...!uknet!nan!sw AppleLink: NAN.LTD Phone: (+44) 203 419996 Mobile:(+44) 850 587411 Fax: (+44) 203 690690 +++++++++++++++++++++++++++ >From paulr@syma.sussex.ac.uk (Paul Russell) Date: Thu, 10 Mar 1994 14:41:27 GMT Organization: University of Sussex Sak Wathanasin (sw@network-analysis-ltd.co.uk) wrote: : In article <1994Mar08.191635.25383@rat.csc.calpoly.edu> (comp.sys.mac.programmer), jclark@galaxy.csc.calpoly.edu (Joseph V Clarke) writes: : > some kind of interrupt handler? My application is real time : > intensive and when someone holds down the menu, my app loses control : > of the mac and the real time is lost (the data is crunched and when : > I release the menu, it gushes out...thereby not accurately representing : > the data.) : > : > I would just like to clear the buffer and eliminate the data if the : > user happened to be in the menu for awhile. Suggestions? : Try using a MenuHook proc: see Inside Mac vol 1 pg 356. I wrote a little background tasking unit for a comms program a few years back and I spent some time working out which traps needed to be patched in order to get regular calls regardless of what the user is doing. It turns out that you can do this by patching two traps - GetNextEvent and OSEventAvail (I think). GetNextEvent gets called most of the time and OSEventAvail gets called when the mouse is down in a menu. (BTW, WaitNextEvent calls GetNextEvent). You need to make sure that your patches are in the System heap so that they still get called when your application is switched to the background. Doing this is much nicer than using VBL's, particularly when it comes to debugging... //Paul -- | Paul Russell | Internet: P.T.Russell@sussex.ac.uk | | Experimental Psychology | AppleLink: EP.SUSSEX | | Sussex University, Falmer | Telephone: +44 273 678639 | | Brighton BN1 9QG, England | Facsimile: +44 273 678433 | +++++++++++++++++++++++++++ >From dean@genmagic.com (Dean Yu) Date: 10 Mar 1994 21:46:46 GMT Organization: General Magic, Inc. In article <1994Mar08.191635.25383@rat.csc.calpoly.edu> (comp.sys.mac.programmer), jclark@galaxy.csc.calpoly.edu (Joseph V Clarke) writes: > some kind of interrupt handler? My application is real time > intensive and when someone holds down the menu, my app loses control > of the mac and the real time is lost (the data is crunched and when > I release the menu, it gushes out...thereby not accurately representing > the data.) > > I would just like to clear the buffer and eliminate the data if the > user happened to be in the menu for awhile. Suggestions? Assuming that this is an application of your own creation, and you're not using some application framework, you know when the user started mousing around in a menu because you called MenuSelect, and you know when the user let go of the button because MenuSelect returns. -- Dean Yu Negative Ethnic Role Model General Magic, Inc. +++++++++++++++++++++++++++ >From KLUEV@jonathan.srcc.msu.su Date: Sat, 12 Mar 1994 21:14:18 +0300 Organization: (none) In article <1994Mar10.144127.15078@syma.sussex.ac.uk> paulr@syma.sussex.ac.uk (Paul Russell) writes: >Sak Wathanasin (sw@network-analysis-ltd.co.uk) wrote: > >: In article <1994Mar08.191635.25383@rat.csc.calpoly.edu> (comp.sys.mac.programmer), jclark@galaxy.csc.calpoly.edu (Joseph V Clarke) writes: >: > some kind of interrupt handler? My application is real time >: > intensive and when someone holds down the menu, my app loses control >: > of the mac and the real time is lost (the data is crunched and when >: > I release the menu, it gushes out...thereby not accurately representing >: > the data.) >: Try using a MenuHook proc: see Inside Mac vol 1 pg 356. > >I wrote a little background tasking unit for a comms program a >few years back and I spent some time working out which traps >needed to be patched in order to get regular calls regardless >of what the user is doing. > >It turns out that you can do this by patching two traps - GetNextEvent and >OSEventAvail (I think). GetNextEvent gets called most of the time and >OSEventAvail gets called when the mouse is down in a menu. (BTW, >WaitNextEvent calls GetNextEvent). > >You need to make sure that your patches are in the System heap so that >they still get called when your application is switched to the background. This "system heapness" works only with VBL's, i.e. if your VBL proc resides in sysHeap, it (proc) will not be swapped on MF switch. This trick will not work with patching traps. It is "near" to be impossible to make a global patch from within an application, so you need an INIT; and if you want not an INIT but an application - you need VBL (or other int. time) Why "near"? One can install a TM or VBL task and patch the trap for currently running application. Red banner. Michael Kluev. --------------------------- >From jfinete@cats.ucsc.edu (Joseph Manuel Finete) Subject: What happens if my Vertical Retrace task takes too long? Date: 3 Mar 1994 01:33:00 GMT Organization: University of California; Santa Cruz My understanding of the vertical retrace manager is that you supply an number of ticks to wait before calling the vertical retrace task, and that your task function should update this number when it's finished. My question is, if my task takes longer than one tick (1/60 th of a second) will the number of ticks between tasks be the number of ticks to complete the task plus the number of interval ticks? Is there any danger in having a vertical retrace task that can't be completed in one tick? -- Joe Finete jfinete@cats.ucsc.edu +++++++++++++++++++++++++++ >From ari@world.std.com (Ari I Halberstadt) Date: Thu, 3 Mar 1994 06:40:51 GMT Organization: The World Public Access UNIX, Brookline, MA In article <2l3eoc$k6q@darkstar.ucsc.edu>, >My understanding of the vertical retrace manager is that you supply an >number of ticks to wait before calling the vertical retrace task, and that >your task function should update this number when it's finished. That's true. >My question is, if my task takes longer than one tick (1/60 th of a >second) will the number of ticks between tasks be the number of ticks >to complete the task plus the number of interval ticks? Is there any >danger in having a vertical retrace task that can't be completed in one >tick? You definitely don't want your task to take longer than 1/60th of a second. In fact, you want it to take substantially less than 1/60th of a second, since there are bound to be other tasks the processor has to handle. If your task takes too long all sorts of things will get messed up, including cursor tracking, the Ticks low-memory global, other VBL tasks that need to be executed every 1/60th of a second, video updates etc. The CPU can accomplish quite a bit of processing in a fraction of 1/60th of a second. If your task is that compute intensive you should probably run it during null event processing. For precise intervals between tasks you should investigate the extended time manager, though even that won't work well if tasks take too long. I've found that time manager tasks on a Mac Plus work ok up to about 1/100th of a second, more frequent than that and the machine gets pretty slow; this probably applies to other 68000 machines, though faster CPUs should be able to handle smaller time slices. -- Ari Halberstadt ari@world.std.com #include "These beetles were long considered to be very rare because very few entomologists look for beetles in the mountains, in winter, at night, during snow storms." -- Purves W. K., et al, "Life: The Science of --------------------------- >From rang@winternet.mpls.mn.us (Anton Rang) Subject: When to StripAddress? (was Re: Let's kill 24-bit mode!) Date: 16 Mar 1994 01:33:27 GMT Organization: Minnesota Angsters In article t-gaul@i-link.com (Troy Gaul) writes: >There are cases where you must call StripAddress for a program to function >correctly in all 'modes'. It is possible that you haven't run across them. One which bit me last year, that I never did find documented.... It's important to call StripAddress() on any value that you pass to InitZone(). Otherwise, something internal to the memory manager starts to strip *some* addresses in the zone, but not others, and it all flies apart.... Other than that, hmm. When you patch traps or change hooks (like the routines in a GrafPort, or low-memory globals), make sure that you call StripAddress() first. The system might switch into 32-bit mode and then call your routine. (I'm sure this happens for very few cases, but I've seen it cause problems before.) And, obviously, if you're switching modes yourself. :-) -- Anton Rang (rang@winternet.mpls.mn.us) --------------------------- >From AIKEN Subject: Why can't I have AEs *in* AEs? Date: Fri, 25 Feb 1994 02:35:52 GMT Organization: McGill University For reasons of my own (yes, I am sick and twisted) I am trying to add an Apple Event to another Apple event as a paramater. My code looks something like: ** AppleEvent AEToSend,AEToInclude; Error=AEPutParamDesc(&AEToSend,keyDirectObject,&AEToInclude); ** the AE Manager just barfs up a -1703 err, "Wrong descriptor type". Is this not something I'm supposed to be contemplating, or am I mis- sing something? The funny thing is, if I do a AEPutParamPtr like: Error=AEPutParamPtr(&AEToSend,keyDirectObject,'aevt', &AEToInclude,sizeof(AppleEvent)); Everything is hunky-dory. However, I'm concerned that this method does not make a true duplicate of AEToInclude, which will definately raise hell down the line. This is confusing, however, because both methods should produce a paramater with the same keyword and descriptor type, no? Insights *greatly* appreciated. Mark Aiken inra@musicb.mcgill.ca +++++++++++++++++++++++++++ >From jwbaxter@olympus.net (John W. Baxter) Date: Fri, 25 Feb 1994 00:43:56 -0800 Organization: Internet for the Olympic Peninsula In article <24FEB94.23325740.0070@VM1.MCGILL.CA>, AIKEN wrote: > For reasons of my own (yes, I am sick and twisted) I am trying to > add an Apple Event to another Apple event as a paramater. My code > looks something like: > > ** > AppleEvent AEToSend,AEToInclude; > > Error=AEPutParamDesc(&AEToSend,keyDirectObject,&AEToInclude); > ** > > the AE Manager just barfs up a -1703 err, "Wrong descriptor type". > Is this not something I'm supposed to be contemplating, or am I mis- > sing something? Hmmm...surprising that it's not allowed (although it's also surprising you want to do this). An Apple Event is almost an AERecord (but not quite). > > The funny thing is, if I do a AEPutParamPtr like: > > Error=AEPutParamPtr(&AEToSend,keyDirectObject,'aevt', > &AEToInclude,sizeof(AppleEvent)); Not a good idea. > > Everything is hunky-dory. However, I'm concerned that this method > does not make a true duplicate of AEToInclude, which will definately > raise hell down the line. This is confusing, however, because both > methods should produce a paramater with the same keyword and descriptor > type, no? No. Look at the AEPutParamPtr again. The third parameter points to an AppleEvent. If you go back far enough, that's just an AEDesc. A type, and a handle. sizeof (AppleEvent) is 8. So you put the 8 bytes (the type), and the value of the address of the block's master pointer into your AEToSend as the '----' parameter. I strongly suspect that's not what you want to do. What MAY work is this: 1. Build your AEToInclude in the usual way. 2. Close your eyes (figuratively), and stuff 'reco' into AEToInclude.descriptorType ['reco' is also known as typeAErecord, and you should use that constant, IMHO]. 3. Now, you should be able to add your AEToInclude to AEToSend with AEPutParamDesc (). 4. On the other end, knowing what is coming in, get the parameter using AEGetParamDesc, and stuff typeAppleEvent ('aevt') into the descriptorType field of the AEDesc. The above will probably work today. It's asking for trouble. Do you *really* want to do this??? Or...can you get by with passing an AERecord, instead? You can make your own AEList of attributes, if needed. -- John Baxter Port Ludlow, WA, USA [West shore, Puget Sound] jwbaxter@pt.olympus.net +++++++++++++++++++++++++++ >From lai@apple.com (Ed Lai) Date: 25 Feb 1994 17:27:15 GMT Organization: Apple > In article <24FEB94.23325740.0070@VM1.MCGILL.CA>, AIKEN > wrote: > > > For reasons of my own (yes, I am sick and twisted) I am trying to > > add an Apple Event to another Apple event as a paramater. My code > > looks something like: > > > > ** > > AppleEvent AEToSend,AEToInclude; > > > > Error=AEPutParamDesc(&AEToSend,keyDirectObject,&AEToInclude); > > ** > > > > the AE Manager just barfs up a -1703 err, "Wrong descriptor type". > > Is this not something I'm supposed to be contemplating, or am I mis- > > sing something? > The Apple Event Manager checks to make sure you cannot stuff an Apple Event inside another Apple Event, list or record. -- /* Disclaimer: All statments and opinions expressed are my own */ /* Edmund K. Lai */ /* Apple Computer, MS303-3A */ /* 20525 Mariani Ave, */ /* Cupertino, CA 95014 */ /* (408)974-6272 */ zW@h9cOi +++++++++++++++++++++++++++ >From AIKEN Date: Fri, 25 Feb 1994 23:27:21 GMT Organization: McGill University In article lai@apple.com (Ed Lai) writes: >The Apple Event Manager checks to make sure you cannot stuff an Apple Event >inside another Apple Event, list or record. Since this is deliberate, I assume there is a logical reason why this is so. However, I don't see it. What gives? Mark Aiken inra@musicb.mcgill.ca +++++++++++++++++++++++++++ >From AIKEN Date: Fri, 25 Feb 1994 23:48:43 GMT Organization: McGill University In article jwbaxter@olympus.net (John W. Baxter) writes: >In article <24FEB94.23325740.0070@VM1.MCGILL.CA>, AIKEN > wrote: > >> For reasons of my own (yes, I am sick and twisted) I am trying to >> add an Apple Event to another Apple event as a paramater. My code >> looks something like: [CHOP -- trying AEPutParamDesc doesn't work.] >> The funny thing is, if I do a AEPutParamPtr like: >> >> Error=AEPutParamPtr(&AEToSend,keyDirectObject,'aevt', >> &AEToInclude,sizeof(AppleEvent)); > >Not a good idea. >> >> Everything is hunky-dory. However, I'm concerned that this method >> does not make a true duplicate of AEToInclude, which will definately >> raise hell down the line. This is confusing, however, because both >> methods should produce a paramater with the same keyword and descriptor >> type, no? > >No. Look at the AEPutParamPtr again. The third parameter points to an >AppleEvent. If you go back far enough, that's just an AEDesc. A type, and >a handle. sizeof (AppleEvent) is 8. So you put the 8 bytes (the type), >and the value of the address of the block's master pointer into your >AEToSend as the '----' parameter. I strongly suspect that's not what you >want to do. I know. What confuses me is this: AEPutParamDesc with the above usage should attempt to add a copy of the supplied Apple Event (type: 'aevt') as the direct paramater. But as a helpful Apple Person (tm) pointed out, the AE Manager specifically watches out for this. However, AEPutParamPtr, with the above usage, *also* tries to add a hunk of data as the direct paramater. The descriptor type, of course, is supplied in the arguments. AEPutParamPtr is inappropriate here because it doesn't copy all the associated data of the AE, just its 8-byte descriptor data. However, I find it confounding that the AE Manager would agree to add a descriptor record of type 'aevt' from certain calls and not from others. >What MAY work is this: >1. Build your AEToInclude in the usual way. >2. Close your eyes (figuratively), and stuff 'reco' into >AEToInclude.descriptorType ['reco' is also known as typeAErecord, and you >should use that constant, IMHO]. >3. Now, you should be able to add your AEToInclude to AEToSend with >AEPutParamDesc (). >4. On the other end, knowing what is coming in, get the parameter using >AEGetParamDesc, and stuff typeAppleEvent ('aevt') into the descriptorType >field of the AEDesc. > >The above will probably work today. It's asking for trouble. I'm having trouble understanding why this is all such a bad idea. An AppleEvent descriptor record just points to a list of other stuff, namely attributes and parameters, right? So why *shouldn't* I be able to add it to another AE? Why is the above likely to break in future? >Do you *really* want to do this??? Or...can you get by with passing an >AERecord, instead? You can make your own AEList of attributes, if needed. I don't *really* have to do this. It's just that at one point, I have data in one AE that another app will need in an AE *it* will send in response to an AE I'm about to send it (read that slowly!). It seemed natural to stuff a copy of the pre-fab AE that the other app will need into the AE I'm about to send it, so that at the other end, the app can remove the enclosed AE, twiddle the address and maybe one or two other things, and send it off. No fuss, no muss. Oh, well. Since both apps know exactly what's supposed to be in the AEs, I can just bundle all the data into *one* AE, that the receiving app can rip apart to put together its own AE. But it would have been nice to be able to send it one already ready to go. I hadn't thought of your solution, though (thanks!), but I would love an explanation as to why it's such a bad idea before I start using it! :-) Mark Aiken inra@musicb.mcgill.ca +++++++++++++++++++++++++++ >From jwbaxter@olympus.net (John W. Baxter) Date: Sat, 26 Feb 1994 00:13:49 -0800 Organization: Internet for the Olympic Peninsula In article <25FEB94.20317060.0081@VM1.MCGILL.CA>, AIKEN wrote: [a few words of quotation left out] > I hadn't thought of your solution, though (thanks!), but I would > love an explanation as to why it's such a bad idea before I start using > it! :-) Apple specifies that once you have done your inserting of something into any of the AE structures, the layout of the contents of the structure are unknown to you. They do that in part because, I suspect, they are darn tired of working around the clever things developers have done with knowledge of such things (like forcing a whole bunch of extra structures in a color window). So, in principal, all you know is that you toss some bytes in one end, and the same byte values come out the other end. Having said that: You say: > An AppleEvent descriptor record just points to a list of other stuff, > namely attributes and parameters, right? No...it only looks that way. At each stage, the structure is flattened, and there's only one handle involved with the AEDesc, which contains copies of everything that has been stuffed in, whether by xxxPtr, or xxxDesc. At least...it's that way this week (see above). -- John Baxter Port Ludlow, WA, USA [West shore, Puget Sound] jwbaxter@pt.olympus.net +++++++++++++++++++++++++++ >From peter@ncrpda.curtin.edu.au (Peter N Lewis) Date: 27 Feb 1994 12:52:03 +0800 Organization: NCRPDA, Curtin University lai@apple.com (Ed Lai) writes: >The Apple Event Manager checks to make sure you cannot stuff an Apple Event >inside another Apple Event, list or record. Stupid question: Why? Peter. -- Peter N Lewis Ph: +61 9 368 2055 +++++++++++++++++++++++++++ >From Patrick C. Beard Date: Mon, 28 Feb 1994 01:38:35 GMT Organization: Dept. Of Computer Science, U.C. Davis In article <24FEB94.23325740.0070@VM1.MCGILL.CA> AIKEN, INRA000@MUSICB.MCGILL.CA writes: > For reasons of my own (yes, I am sick and twisted) I am trying to >add an Apple Event to another Apple event as a paramater. My code >looks something like: > >** >AppleEvent AEToSend,AEToInclude; > > Error=AEPutParamDesc(&AEToSend,keyDirectObject,&AEToInclude); >** > > the AE Manager just barfs up a -1703 err, "Wrong descriptor type". >Is this not something I'm supposed to be contemplating, or am I mis- >sing something? I ran into the same problem. My solution? Lie to the AppleEvent manager. There's no reason it has to know the type of a parameter. Just make up one of your own. Since an AppleEvent is just an AEDesc with a descriptorType and a dataHandle, and the type is always 'aevt', just do the following: OSErr StuffAE(AppleEvent* event, AppleEvent* nestedEvent) { OSErr result; Handle eventData = nestedEvent->dataHandle; HLock(eventData); result = AEPutParamPtr(&event, keyDirectObject, 'stuff', *eventData, GetHandleSize(eventData)); HUnlock(eventData); return result; } I've used this approach, and it works. // // Patrick C. Beard // Dept. of Computer Science, U. C. Davis // beard@cs.ucdavis.edu // +++++++++++++++++++++++++++ >From lai@apple.com (Ed Lai) Date: 5 Mar 1994 00:36:19 GMT Organization: Apple In article <25FEB94.19932459.0081@VM1.MCGILL.CA>, AIKEN wrote: > In article lai@apple.com (Ed Lai) writes: > >The Apple Event Manager checks to make sure you cannot stuff an Apple Event > >inside another Apple Event, list or record. > > Since this is deliberate, I assume there is a logical reason why > this is so. However, I don't see it. What gives? > > Mark Aiken > inra@musicb.mcgill.ca Well, the answer is that the Apple Event Manager is just one of the implementations of Apple Event, and the Apple Event Transport Format (it is in one of the tech note) specifies that there can be no Apple Event embedded in another Apple Event. Then the question is why the AETF specifies this. I guess it is partly not to make it too complicated, and partly because an embedded Apple Event can be misleading. Let say you create Apple Event A and B in a machine X with some valid session id as the target address, you embed B into A and send it off to another machine. When it arrives at the other machine Y, the adress of Apple Event A will be valid on arrival. However, if you pull out the Apple Event B from Apple Event A, you get an Apple Event with an session ID from machine X which is invalid in machine Y. -- /* Disclaimer: All statments and opinions expressed are my own */ /* Edmund K. Lai */ /* Apple Computer, MS303-3A */ /* 20525 Mariani Ave, */ /* Cupertino, CA 95014 */ /* (408)974-6272 */ zW@h9cOi --------------------------- >From dresden@albert.ma.utexas.edu (Greg Dresden) Subject: Why use handles at all, though? Date: 1 Mar 1994 16:43:35 -0600 Organization: University Of Texas Mathematics Concerning the current debate about handles: I've been reading with great interest these articles about when to lock 'em, when to unlock 'em, and when to walk away. >From what I can pick up, it seems as if these handles are simply pointers to pointers. (Alas, I must have been asleep when we discussed these in class.) If this is so, why would anyone want to: (a) use handles when you could just use pointers, and (b) use a "with" statement when you could just type out the pointer's full name (thus saving yourself much grief.) Now, I am a still-wet-behind-the-ears newbie, but I can't really see the value of handles as a programming tool. Are there any enlightened gurus out there who would like to rush to the defense of these much-maligned objects? - -------------------------------------------------- dresden@albert.ma.utexas.edu +++++++++++++++++++++++++++ >From mssmith@afterlife.ncsc.mil (M. Scott Smith) Date: Wed, 2 Mar 1994 13:10:43 GMT Organization: The Great Beyond In article <2l0gen$k3e@albert.ma.utexas.edu> dresden@albert.ma.utexas.edu (Greg Dresden) writes: >Concerning the current debate about handles: > >I've been reading with great interest these articles about when to lock 'em, >when to unlock 'em, and when to walk away. > >From what I can pick up, it seems as if these handles are simply >pointers to pointers. (Alas, I must have been asleep when we discussed these >in class.) > >If this is so, why would anyone want to: (a) use handles when you could >just use pointers [...] I'll try to tackle this one.. Memory management on the Macintosh is different than most other computers. When the Mac first came out, it didn't have much memory available for applications' use. And Mac programs -- being graphical, etc., tended to take up more memory than their text counterparts (even though a lot of the Toolbox calls were in ROM.) Because of this, it was necessary to create a very efficient memory model. Let's first look at the traditional way of allocating memory with pointers. When you first run a program, a chunk of memory is set aside. Then, whenever you call NewPtr, you're taking away from that chunk. Say the memory partition is 200 kilobytes. You go along and allocate 100k with a pointer. Now memory looks like this: - -- |XX| 100k (allocated) |XX| |--| | | 100k (available) | | - -- Now you allocate 30k. After that, you deallocate the 100k. Now memory looks like this: - -- | | 100k (available) | | |XX| 30k (allocated) | | | | 70k (available) - -- Now say you need to allocate 110k. You can't. You can allocate up to 100k, but no more, even though you've technically got 170k available. Why? Because you've fragmented the heap, as they say. I've really simplified things here; you can imagine just how fragmented the heap can get before too long, especially if it's not all that large to begin with (the ideal). Wouldn't it be great if the computer was smart enough to, say, move that 30k down to the bottom of the heap so you could allocate the whole 170k? Enter handles. As if pointers weren't confusing enough, now you've got pointers to pointers (to pointers to pointers to..) Say we wanted to solve our problem using pointers; we wanted to make the computer intelligent enough to rearrange memory. The problem is, we've got a local variable which is a pointer to a memory address that locates your allocation on the heap. If the memory manager moved your allocation on the heap, your pointer would still be pointing at the old address -- which is most likely NOT what you want. (Unless you're one of those "grunge" programmers.) With handles, you still maintain a pointer, but it points to a pointer which is maintained by the memory manager, and not you. That way, the memory manager is free to do anything it wants with memory -- so long as it updates that pointer it's maintaining to reflect the new location of your memory. So long as you use YOUR pointer, you will be safe; it will always be pointing to a pointer which points to the correct address of your memory, even if that address changes. Other issues come up, though. Dereferencing a pointer twice is a lot slower than dereferencing a pointer once, so you'll probably want to dereference that handle to get to the pointer that points straight to the data, when you want to access that data. This can be dangerous, because the memory manager can change it at any time (and your dereference won't reflect that change!) When can the memory manager move things around in the heap? Just about anytime it feels like it. Many (most?) of the Toolbox functions can trigger memory manager activity. If you do dereference a handle, you should be careful that memory isn't going to move; if you're uncertain, you can "lock" the handle down, which guarantees the memory manager won't move it. (You should unlock it when you're done so it can move it. After all, that's the whole point.) Does that help clear things up a bit? Scott - - M. Scott Smith Macintosh developer, student, ski bum. Eater of Cadbury's Creme Eggs. +++++++++++++++++++++++++++ >From gurgle@netcom.com (Pete Gontier) Date: Wed, 2 Mar 1994 19:51:32 GMT Organization: cellular dresden@albert.ma.utexas.edu (Greg Dresden) writes: >I've been reading with great interest these articles about when to >lock 'em, when to unlock 'em, and when to walk away. From what I can >pick up, it seems as if these handles are simply pointers to pointers. >(Alas, I must have been asleep when we discussed these in class.) If >this is so, why would anyone want to: (a) use handles when you could >just use pointers... What's misleading about many articles which discuss the pitfalls of handle-based memory management is that they focus on the pitfalls, not surprisingly. In fact, there is so much discussion of the pitfalls that it must seem like handles are just a bogus design waiting to cause bugs in otherwise innocent programs. However, handles have real positive effects when used in low-memory siuations, because they can be moved and recombined and shuffled in general within a heap to make the maximum possible blocks size available to whoever needs it. > ...and (b) use a "with" statement when you could just type out the >pointer's full name (thus saving yourself much grief.) Most people use WITH statements just for convenience. In some cases, that convenience can be non-trivial. Suppose you have several nested records. You know that a certain piece of code wants to access the fields of one of the most deeply nested records. Suppose further that you would like to be able to reorganize the containment structure of this deeply nested record if and when necessary. The WITH statement, used properly, would theoretically allow you to change less code, thereby reducing the chance of introducing a typographical error which coincidentally compiles without error. In most cases, though, I think you're right: WITH is just expedient. >Are there any enlightened gurus out there who would like to rush to the >defense of these much-maligned objects? IMO (and there are plenty who disagree with me), the era of handles is largely over. People used to allocate handles whenever they needed a hunk of memory out of the heap. This was necessary because the Mac had very little memory. Now that customers expect applications to be huge, I think you can get away with allocating pointers a lot of the time. Large chunks of memory should probably still be in pointers. Also, don't conclude that I think applications can be and should be huge these days. That's obviously an unsupportable position. I am merely pointing out that since many apps are huge, there's a little more weight on the side of the scale for safety and robustness (pointers) than there used to be. Also, don't use NewPtr or malloc. But that's another story altogether. -- Pete Gontier, CTO, Integer Poet Software; gurgle@netcom.com +++++++++++++++++++++++++++ >From u9119523@sys.uea.ac.uk (Graham Cox) Date: Thu, 3 Mar 1994 15:43:15 GMT Organization: School of Information Systems, UEA, Norwich In article , gurgle@netcom.com (Pete Gontier) wrote: > dresden@albert.ma.utexas.edu (Greg Dresden) writes: > [SNIP!] Just to add my two-penn'orth... Once you understand WHY handles exist and HOW to use them, you hardly ever use pointers again, and your ability as a programmer of truly stable, solid Mac programs takes a massive leap forward. That was my experience anyway (was it really 1986...?) - ------------------------------------------------------------------------ Love & BSWK, Graham -Everyone is entitled to their opinion, no matter how wrong they may be... - ------------------------------------------------------------------------ +++++++++++++++++++++++++++ >From gurgle@netcom.com (Pete Gontier) Date: Thu, 3 Mar 1994 20:52:39 GMT Organization: cellular gurgle@netcom.com (Pete Gontier) writes: >Large chunks of memory should probably still be in pointers. Yow! Here I was trying to be responsible and I let a zinger like THIS go by. It should have read: >Large chunks of memory should probably still be in handles. -- Pete Gontier, CTO, Integer Poet Software; gurgle@netcom.com +++++++++++++++++++++++++++ >From rang@winternet.mpls.mn.us (Anton Rang) Date: 04 Mar 1994 00:35:07 GMT Organization: Minnesota Angsters In article gurgle@netcom.com (Pete Gontier) writes: >However, handles have real positive >effects when used in low-memory siuations, because they can be moved and >recombined and shuffled in general within a heap to make the maximum >possible blocks size available to whoever needs it. Not just in low-memory situations, either; any time that you need to have a memory block whose size varies dynamically, a handle is *very* useful.... -- Anton Rang (rang@acm.org) +++++++++++++++++++++++++++ >From Brad Koehn Date: 4 Mar 1994 01:30:22 GMT Organization: University of Wisconsin In article Pete Gontier, gurgle@netcom.com writes: >IMO (and there are plenty who disagree with me), the era of handles is >largely over. I guess I'm one of those people. >People used to allocate handles whenever they needed a >hunk of memory out of the heap. This was necessary because the Mac had >very little memory. That's still true. You can never have enough memory, and one pointer can cut the RAM you have in half, no matter how much you have. I'm kind of a purist, I love the Mac memory model (well, not all of it, but within a heap anyway) and thinks it's just great. I can make great programs that require hardly any memory to run, and they have all kinds of cool memory management w/o requiring an MMU. As long as I assume that my handles are going to move all the time, everything's kosher. Wait, that's not true. My handles don't move all the time, they only do during most trap calls. I don't bother to check which ones (unless I'm in speed critical code), I just lock and unlock as necessary. As it turns out, it's usually not all that necessary. And on top of that, I get a nice clean heap. I do wish that HLock and HUnlock weren't traps though, it bothers me that my precious clock cycles are being stolen by the trap dispatcher (esp. with TCL...). _________________________________________________________________________ Brad Koehn Data Transformations, Inc. koehn@macc.wisc.edu +++++++++++++++++++++++++++ >From ldo@waikato.ac.nz (Lawrence D'Oliveiro, Waikato University) Date: 4 Mar 94 17:02:44 +1300 Organization: University of Waikato, Hamilton, New Zealand In article <2l0gen$k3e@albert.ma.utexas.edu>, dresden@albert.ma.utexas.edu (Greg Dresden) writes: > Concerning the current debate about handles: > > I've been reading with great interest these articles about when to lock 'em, > when to unlock 'em, and when to walk away. > > From what I can pick up, it seems as if these handles are simply > pointers to pointers. (Alas, I must have been asleep when we discussed these > in class.) Ar, that be right. > If this is so, why would anyone want to: (a) use handles when you could > just use pointers,... The thing about handles is that the memory blocks can move about in memory. This has two consequences: 1) Fragmentation is less likely when memory is running low, and 2) You can resize the blocks. Reason 1 is less important when you have megabytes to play with. However, 2 is still a very useful property: it's handy for creating all kinds of dynamically-sized structures--arrays and the like. > and (b) use a "with" statement when you could just > type out the pointer's full name (thus saving yourself much grief.) Beats me, too... > Now, I am a still-wet-behind-the-ears newbie, but I can't really > see the value of handles as a programming tool. I trust I have managed to disabuse you of that notion. Lawrence a member of the society for linking things to other things. +++++++++++++++++++++++++++ >From D.A.G.Gillies@bradford.ac.uk (DAG GILLIES) Date: Fri, 4 Mar 1994 12:40:41 GMT Organization: University of Bradford, UK In article gurgle@netcom.com (Pete Gontier) writes: >dresden@albert.ma.utexas.edu (Greg Dresden) writes: > >>Are there any enlightened gurus out there who would like to rush to the >>defense of these much-maligned objects? > >IMO (and there are plenty who disagree with me), the era of handles is >largely over. People used to allocate handles whenever they needed a >hunk of memory out of the heap. This was necessary because the Mac had >very little memory. Now that customers expect applications to be huge, >I think you can get away with allocating pointers a lot of the time. >Large chunks of memory should probably still be in pointers. Also, don't >conclude that I think applications can be and should be huge these days. >That's obviously an unsupportable position. I am merely pointing out >that since many apps are huge, there's a little more weight on the side >of the scale for safety and robustness (pointers) than there used to be. >Also, don't use NewPtr or malloc. But that's another story altogether. >-- I like handles from an aesthetic point of view - they seem to me to be a nice way of handling dynamic memory. I have a general rule of thumb for when to use handles and when to use pointers, and it relies mainly on the scope and lifetime of the entity for which storage is being allocated. In general, if I am allocating an object at global scope, I will use a handle, to allow that object to waft around the heap and maximise available memory. Typically, where it is being used in a function, I will lock it down (and high) with HLockHi for the duration of that function and than free it up again at the end. This allows me to dereference it once at the beginning of the function for speed. However, if I am allocating an object that only exists at local scope, and which will be destroyed when the enclosing function returns, I will use a pointer, unless the object is needed by a lot of functions called by the enclosing function, in which case I may well use a Handle (and possibly lock it down as before). If I am messing with resource creation (like building Finder aliases), I will use Handles, simply because resources are Handles themselves, and in general speed is not critical in such cases. ______________________________________________________ David A. G. Gillies (D.A.G.Gillies@bradford.ac.uk) (c) 1994 Wittgenstein's Amazing Underwater Supermarket - -------------REPLIES VIA EMAIL PLEASE--------------- _/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ +++++++++++++++++++++++++++ >From partingt@fwi.uva.nl (Vincent Partington) Date: 4 Mar 1994 16:08:49 GMT Organization: FWI, University of Amsterdam gurgle@netcom.com (Pete Gontier) writes: >>Large chunks of memory should probably still be in pointers. >Yow! Here I was trying to be responsible and I let a zinger like THIS go >by. It should have read: >>Large chunks of memory should probably still be in handles. It doesn't really matter if you put large or small objects in handles. Small objects break up the heap just as good as big objects. So if you go with handles, go with them all the way. Vincent. BTW, Why isn't there a TempNewPtr call? To prevent us from cluttering the temporary heap? -- VI is better than Emacs. | Let's | Internet : partingt@fwi.uva.nl MacOS is better than Windows. | start the | vincent@tnc.nl Unix is better than VMS. | religious | FidoNet : 2:281/202.15 Eiffel is better than C++. | war!! | NeST : 90:500/202.15 +++++++++++++++++++++++++++ >From gurgle@netcom.com (Pete Gontier) Date: Fri, 4 Mar 1994 20:09:41 GMT Organization: cellular rang@winternet.mpls.mn.us (Anton Rang) writes: >In article gurgle@netcom.com (Pete Gontier) writes: >>However, handles have real positive >>effects when used in low-memory siuations, because they can be moved and >>recombined and shuffled in general within a heap to make the maximum >>possible blocks size available to whoever needs it. >Not just in low-memory situations, either; any time that you need to >have a memory block whose size varies dynamically, a handle is *very* >useful.... That depends on how you define "useful", of course. If you are, for example, talking about adding a couple of bytes to a handle which takes up more than half the heap, which would be impossible without handles, I would call that part of the low-memory considerations. The other aspects of it are about convenience and performance, not space savings. And it's true that these also are reasons to advocate handles. But if you can't do something at all, it doesn't matter how convenient or fast it would have been. :-) -- Pete Gontier, CTO, Integer Poet Software; gurgle@netcom.com +++++++++++++++++++++++++++ >From gurgle@netcom.com (Pete Gontier) Date: Fri, 4 Mar 1994 20:18:09 GMT Organization: cellular Brad Koehn writes: > ...one pointer can cut the RAM you have in half, no matter how much > you have. Sure, that's true. But I'd say it's easier for the most part to keep this in mind and avoid it rather than use handles all the time. I'm not suggesting people allocate pointers for long-term global-state storage. If, well into a program's lifetime, it decides it's going to allocate a text buffer and leave it hanging around indefinitely, that buffer shouldn't go into a pointer. For all it knows, a properly written function has been called deep in a call hierarchy, and several bazillion pointers may already have been allocated on the heap. Allocating another and leaving it around could easily frag the heap and reduce the amount of memory available to any one block. >My handles don't move all the time, they only do during most trap >calls. I don't bother to check which ones (unless I'm in speed critical >code), I just lock and unlock as necessary. I usually assume StripAddress and BlockMove are not going to move memory, but that's about it. :-) BTW, also remember to be paranoid about inter-segment calls. -- Pete Gontier, CTO, Integer Poet Software; gurgle@netcom.com +++++++++++++++++++++++++++ >From mxmora@unix.sri.com (Matt Mora) Date: 4 Mar 1994 09:27:52 -0800 Organization: SRI International, Menlo Park, CA In article <2l62ve$97p@news.doit.wisc.edu> Brad Koehn writes: >In article Pete Gontier, gurgle@netcom.com >writes: >>IMO (and there are plenty who disagree with me), the era of handles is >>largely over. > >I guess I'm one of those people. Me too. (if your talking about wanting to keep Handles) I think Handles are cool but always wished they did more. Why couldn't handles, when being moved to make room, jump over locked blocks? Handles can become pretty useless if there are a few locked blocks in memory. I think handles should have been more automagic. The memeory manager should take care of the details for me. For example. Why couldn't we call one function to tell the memory manager that we are about to use the data thats in the handle. ie: HUsingHandle(h); HNotUsingHandle(h); After marking the handle as not in use, the system is now free to do anything it wants with the handle. That includes paging it to disk, moving it around, jumping over locked memory islands, or even compressing it. Certain functions would call these functions internally like DrawPicture. So you know that when you call drawpicture the system would do anything that it needs to bring the handle to a safe state and then use the data. With the PowerPC machines, things like this are possible. Xavier -- ___________________________________________________________ Matthew Xavier Mora Matt_Mora@qm.sri.com SRI International mxmora@unix.sri.com 333 Ravenswood Ave Menlo Park, CA. 94025 +++++++++++++++++++++++++++ >From j-norstad@nwu.edu (John Norstad) Date: Fri, 04 Mar 1994 18:41:08 -0600 Organization: Northwestern University In article <2l0gen$k3e@albert.ma.utexas.edu>, dresden@albert.ma.utexas.edu (Greg Dresden) wrote: > Are there any enlightened gurus out there who would like to rush to the > defense of these much-maligned objects? Yes, I will. Relocatable memory blocks are incredibly useful for storying varying amounts of data when you don't know in advance how much memory you are going to need, and when the memory needs grow and shrink during the lifetime of the block. The Mac memory manager can easily make a relocatable block larger by moving it or by moving other relocatable blocks out of the way. This is not possible in fixed block systems. This is incredibly useful. All of my Mac programs make extensive use of this feature of the Mac memory manager, and would be very significantly more difficult to write on a system without relocatable blocks. For example, in my NewsWatcher program, I use this in dozens of places. It's an extraordinarily useful technique. I have grow so accustomed to having it that I find it difficult to live without it when I have to deal with programming on other systems. Programing without relocatable and growable blocks is like returning to the pre-Mac stone ages for me. SetHandleSize(h, GetHandleSize(h) + n) is one of my favorite lines of C on the Mac, and is one of the many reasons I find programming the Mac to be much more fun and pleasant than programming other kinds of computers. Yes, you do have to be very careful about dangling pointers. It's the price paid for the flexibility. I have also used a system (Control Data's NOS/VE) where each process could use a very large number of very large separate virtual address spaces. On those systems, you put varying size objects in their own address space. -- John Norstad Academic Computing and Network Services Northwestern University j-norstad@nwu.edu +++++++++++++++++++++++++++ >From ari@world.std.com (Ari I Halberstadt) Date: Sat, 5 Mar 1994 11:18:56 GMT Organization: The World Public Access UNIX, Brookline, MA In article <2l7r2o$t2f@unix.sri.com>, Matt Mora wrote: >Me too. (if your talking about wanting to keep Handles) I think Handles >are cool but always wished they did more. Why couldn't handles, when being If we're on the subject of wish lists... How about a language with a decent garbage collection coroutine? Since the garbage collector would track all memory references, we could let the garbage collector automagically compact the heap for us. Handles would be obsolete and most memory errors would be obsolete (e.g., using disposed memory, forgetting to dispose of memory, even address and bus errors would be very rare with such a language). To top it all off, our programs would be a heck of a lot simpler and easier to write and maintain. I wouldn't worry too much about speed. Algorithms are always getting better, and we can always just throw another CPU at the problem (i.e., parallelize the garbage collection). -- Ari Halberstadt ari@world.std.com #include "These beetles were long considered to be very rare because very few entomologists look for beetles in the mountains, in winter, at night, during snow storms." -- Purves W. K., et al, "Life: The Science of +++++++++++++++++++++++++++ >From gurgle@netcom.com (Pete Gontier) Date: Sat, 5 Mar 1994 22:28:41 GMT Organization: cellular partingt@fwi.uva.nl (Vincent Partington) writes: >gurgle@netcom.com (Pete Gontier) writes: >>>Large chunks of memory should probably still be in pointers. >>Yow! Here I was trying to be responsible and I let a zinger like THIS go >>by. It should have read: >>>Large chunks of memory should probably still be in handles. >It doesn't really matter if you put large or small objects in handles. >Small objects break up the heap just as good as big objects. So if you go >with handles, go with them all the way. I don't think this is valid. If you know what you are doing, it does in fact make sense to put small objects in pointers and large objects in handles in many contexts. Size is not the only consideration, as I posted elsewhere; however, large objects should probably go in handles regardless of other considerations; I believe that would have been more evident if I had quoted more of the original message. -- Pete Gontier, CTO, Integer Poet Software; gurgle@netcom.com +++++++++++++++++++++++++++ >From ldo@waikato.ac.nz (Lawrence D'Oliveiro, Waikato University) Date: 7 Mar 94 14:57:51 +1300 Organization: University of Waikato, Hamilton, New Zealand In article , u9119523@sys.uea.ac.uk (Graham Cox) writes: > > Once you understand WHY handles exist and HOW to use them, you hardly ever > use pointers again, and your ability as a programmer of truly stable, solid > Mac programs takes a massive leap forward. That was my experience anyway > (was it really 1986...?) My Mac experience dates from about the same time (I started getting seriously into Mac programming about 86/87), and I would say "No way!". I wrote some code which created a sorted tree structure once. Initially each block was relocatable. Every now and then, the program would print garbage for the contents of a tree node. Obviously a block was moving unexpectedly from under me. Rather than try to track down the exact place where I was forgetting to lock the block, I changed all the relocatable blocks for the tree nodes to nonrelocatable ones. This is how a conventional tree or linked list structure is built in the textbooks, anyway. The program worked fine after that. Moral: use nonrelocatable blocks for large numbers of identically-sized blocks. I don't think that creating large numbers of handles is a good idea (unless you manage the master pointers quite carefully). If you're doing a lot of allocating and deallocating of blocks of a particular size, you could create a lookaside list to speed things up. I tend to use handles where the system encourages (or forces) me to, and where I need resizable structures. And, yes, I do make frequent use of resizable structures. Lawrence D'Oliveiro fone: +64-7-856-2889 Info & Tech Services Division fax: +64-7-838-4066 University of Waikato electric mail: ldo@waikato.ac.nz Hamilton, New Zealand 37^ 47' 26" S, 175^ 19' 7" E, GMT+13:00 +++++++++++++++++++++++++++ >From bcollett@hamilton.edu (Brian Collett) Date: 8 Mar 1994 17:13:07 GMT Organization: Hamilton College In article <1994Mar7.145751.26071@waikato.ac.nz>, ldo@waikato.ac.nz (Lawrence D'Oliveiro, Waikato University) wrote: > Moral: use nonrelocatable blocks for large numbers of identically-sized blocks. > I don't think that creating large numbers of handles is a good idea (unless > you manage the master pointers quite carefully). If you're doing a lot of > allocating and deallocating of blocks of a particular size, you could create > a lookaside list to speed things up. I tend to use handles where the system > encourages (or forces) me to, and where I need resizable structures. If you are manipulating large numbers of identical blocks then it is highly advantageous to pre-allocate a large chunk of them and then manage them yourself (I use a simple linked list of free blocks). Identical size blocks have no fragmentation problems and you can write a MUCH faster memory manager for them. I have cut the memory manager overhead in a program that manipulates many dynamic blocks from >50% of the total execution time to <10% by this trick. Brian Collett, Physics Dept., Hamilton College, Clinton, NY 13323 +++++++++++++++++++++++++++ >From Brad Miller Date: Tue, 8 Mar 1994 17:16:27 -0500 Organization: University of Rochester Computer Science Dept >>>>> "Ari" == Ari I Halberstadt writes: Ari> In article <2l7r2o$t2f@unix.sri.com>, Matt Mora wrote: >> Me too. (if your talking about wanting to keep Handles) I think Handles are cool but always wished they did >> more. Why couldn't handles, when being Ari> If we're on the subject of wish lists... Ari> How about a language with a decent garbage collection coroutine? Since the garbage collector would track all Ari> memory references, we could let the garbage collector automagically compact the heap for us. Handles would be Ari> obsolete and most memory errors would be obsolete (e.g., using disposed memory, forgetting to dispose of Ari> memory, even address and bus errors would be very rare with such a language). To top it all off, our programs Ari> would be a heck of a lot simpler and easier to write and maintain. I wouldn't worry too much about Ari> speed. Algorithms are always getting better, and we can always just throw another CPU at the problem (i.e., Ari> parallelize the garbage collection). -- Ari Halberstadt ari@world.std.com #include "These Ari> beetles were long considered to be very rare because very few entomologists look for beetles in the mountains, Ari> in winter, at night, during snow storms." -- Purves W. K., et al, "Life: The Science of It already exists, it's called "Lisp". The apple implementation, "Macintosh Common Lisp" is quite good too. Handles shouldn't be needed with any "real" VM. Arguably, the same is true for garbage, if you have a big enough heap. +++++++++++++++++++++++++++ >From tblanch@lookout.ecte.uswc.uswest.com (Todd Blanchard) Date: Mon, 7 Mar 1994 23:44:48 GMT Organization: US WEST Information Technologies Graham Cox (u9119523@sys.uea.ac.uk) wrote: : In article , gurgle@netcom.com (Pete Gontier) : wrote: : > dresden@albert.ma.utexas.edu (Greg Dresden) writes: : > : [SNIP!] : Just to add my two-penn'orth... : Once you understand WHY handles exist and HOW to use them, you hardly ever : use pointers again, and your ability as a programmer of truly stable, solid : Mac programs takes a massive leap forward. That was my experience anyway : (was it really 1986...?) Perhaps, but I'm rather used to doing things like: myObject = new Object(); myObject->Message(); delete myObject; This is the very stuff of C++ and I really like it. Handles are OK for buffers and such but they don't make C++ very nice to implement. A good VM system sort of negates the value of the things. JMO Todd Blanchard +++++++++++++++++++++++++++ >From peirce@outpost.SF-Bay.org (Michael Peirce) Date: Fri, 11 Mar 94 11:23:45 PST Organization: Peirce Software, Inc. In article (comp.sys.mac.programmer), j-norstad@nwu.edu (John Norstad) writes: > In article <2l0gen$k3e@albert.ma.utexas.edu>, dresden@albert.ma.utexas.edu > (Greg Dresden) wrote: > > > Are there any enlightened gurus out there who would like to rush to the > > defense of these much-maligned objects? > > Yes, I will. > > Relocatable memory blocks are incredibly useful for storying varying > amounts of data when you don't know in advance how much memory you are > going to need, and when the memory needs grow and shrink during the > lifetime of the block. > > The Mac memory manager can easily make a relocatable block larger by > moving it or by moving other relocatable blocks out of the way. This is > not possible in fixed block systems. > > This is incredibly useful. All of my Mac programs make extensive use of > this feature of the Mac memory manager, and would be very significantly > more difficult to write on a system without relocatable blocks. I agree with John. Handles are really useful mainly because they are resizable. You simply can't do this with simple pointers. I don't really understand why some people want to banish handles and regress to a pointer only memory model. Yuck. -- Michael Peirce -- peirce@outpost.sf-bay.org -- Peirce Software, Inc. -- 719 Hibiscus Place, Suite 301 -- -- San Jose, California USA 95117 -- Makers of: Smoothie & -- voice: +1.408.244.6554 fax: +1.408.244.6882 -- Peirce Print Tools -- AppleLink: peirce & America Online: AFC Peirce +++++++++++++++++++++++++++ >From platypus@cirrus.som.cwru.edu (Gary Kacmarcik) Date: 11 Mar 1994 23:13:44 GMT Organization: Case Western Reserve University, Cleveland, Ohio (USA) In article peirce@outpost.SF-Bay.org (Michael Peirce) writes: > > In article (comp.sys.mac.programmer), j-norstad@nwu.edu (John Norstad) writes: > > > > Relocatable memory blocks are incredibly useful for storying varying > > amounts of data when you don't know in advance how much memory you are > > going to need, and when the memory needs grow and shrink during the > > lifetime of the block. > > > > The Mac memory manager can easily make a relocatable block larger by > > moving it or by moving other relocatable blocks out of the way. This is > > not possible in fixed block systems. > > I agree with John. Handles are really useful mainly because they > are resizable. You simply can't do this with simple pointers. while i agree that handles are useful. pointers _can_ be resizable. for example, the following routine: int ReallocPtr(Ptr *p,Size newSize) { Ptr new_p; // try to resize the pointer SetPtrSize(p,newSize); if(MemError() == noErr) return(0); // couldn't simply resize, re-allocate the ptr new_p = NewPtrClear(newSize); if(MemError() != noErr) return(1); // copy the data from the old area to the new area BlockMove(*p,new_p,GetPtrSize(*p)); // trash the old ptr DisposePtr(*p); *p = new_p; return(0); } this does basically the same thing that ResizeHandle() does with handles or that realloc() does for pointers in ANSI C. anyway, handles are more convenient than using the above code, but i just wanted to show that Ptr's _can_ be resized. -gary j kacmarcik platypus@curie.ces.cwru.edu +++++++++++++++++++++++++++ >From u9119523@sys.uea.ac.uk (Graham Cox) Date: Fri, 11 Mar 1994 12:37:54 GMT Organization: School of Information Systems, UEA, Norwich In article , tblanch@lookout.ecte.uswc.uswest.com (Todd Blanchard) wrote: > Graham Cox (u9119523@sys.uea.ac.uk) wrote: > : In article , gurgle@netcom.com (Pete Gontier) > : wrote: > > : > dresden@albert.ma.utexas.edu (Greg Dresden) writes: > : > > : [SNIP!] > > : Just to add my two-penn'orth... > > : Once you understand WHY handles exist and HOW to use them, you hardly ever > : use pointers again, and your ability as a programmer of truly stable, solid > : Mac programs takes a massive leap forward. That was my experience anyway > : (was it really 1986...?) > > Perhaps, but I'm rather used to doing things like: > > myObject = new Object(); > myObject->Message(); > delete myObject; Yeah, me too! > > This is the very stuff of C++ and I really like it. Handles are OK for > buffers and such but they don't make C++ very nice to implement. A good > VM system sort of negates the value of the things. > > JMO > Todd Blanchard I don't see why. A handle is a mechanism for implemeinting efficient memory usage. In the original (non C++) implementation of the THINK class library objects WERE handles. Did the programmer care? No- the indirection was hidden from the programmer. Upshot- easy to write syntax PLUS efficient memory management. In C++ I believe that objects are pointers. What difference does it make to the programmer?- none. The syntax is identical. The code is portable. However the fragmentation problem is still there, and presumably C++ apps either suffer as a result or have their own memory management code. Personally, though I'm very much sold on OOP, I still like and appreciate handles, and would prefer that C++ implemented object as handles. - ------------------------------------------------------------------------ Love & BSWK, Graham -Everyone is entitled to their opinion, no matter how wrong they may be... - ------------------------------------------------------------------------ +++++++++++++++++++++++++++ >From rang@winternet.mpls.mn.us (Anton Rang) Date: 12 Mar 1994 04:48:12 GMT Organization: Minnesota Angsters In article platypus@cirrus.som.cwru.edu (Gary Kacmarcik) writes: >while i agree that handles are useful. pointers _can_ be resizable. > [ ... example of re-allocating pointers, pass in ptr, pass out ptr ... ] The problem with re-allocating a pointer using such a routine is that it doesn't update any *other* pointers to the same memory block. So if you have a data structure whose size needs to change, you need to track every pointer to it. At that point, you're just re-inventing handles. -- Anton Rang (rang@winternet.mpls.mn.us) +++++++++++++++++++++++++++ >From gurgle@netcom.com (Pete Gontier) Date: Sat, 12 Mar 1994 06:03:23 GMT Organization: cellular platypus@cirrus.som.cwru.edu (Gary Kacmarcik) writes: >while i agree that handles are useful. pointers _can_ be resizable. >for example, the following routine: >int ReallocPtr(Ptr *p,Size newSize) { > ... > return(0); > } If this is an actual routine you are using, allow me to make a suggestion. Since it always returns 0, you might care to change it so it returns the resized pointer. void * ReallocPtr (void *p, Size newSize); I am using something like this and it works dandy. What returning the resized pointer buys you is less nasty casting to get the parameter right. With the original version, you might have to do something like this: void foo (int *bar) { int x = ReallocPtr ((Ptr *) &bar, sizeof (*bar)); } I know I would get this cast wrong more often than I care to admit. With the newer declaration, you could write the same function like this: void foo (int *bar) { bar = ReallocPtr (bar,sizeof (*bar)); } -- Pete Gontier, CTO, Integer Poet Software; gurgle@netcom.com +++++++++++++++++++++++++++ >From john_werner@taligent.com (John Werner) Date: Sat, 12 Mar 1994 07:18:31 GMT Organization: Taligent, Inc. In article , u9119523@sys.uea.ac.uk (Graham Cox) wrote: > In the original (non C++) implementation of the THINK class library > objects WERE handles. They still are, unfortunately. > Did the programmer care? Yes. You have to be very careful to lock TCL objects if you're going to pass around pointers to any of their fields. References make this even worse, since it's not clear from looking at a piece of code whether references are involved. Code as innocuous looking as this: class foo : public TObject { Complex a, b; Complex bar(); }; Complex foo::bar() { return a + b; } can screw you up if operator+ uses references and foo::bar is in an unloaded segment. It could be argued that this is a compiler bug. The C++ standard (such as it is) says that references and pointers are supposed to refer or point to the original object for as long as it exists. In this case they don't. > Upshot- easy to write syntax PLUS efficient memory management. It's quite possible to write an efficient pointer-based memory manager. Heaps may take up a bit more space, but they're a lot faster, since you can don't have to move blocks around all the time. With decent virtual memory, large resizable blocks like editing buffers aren't a big issue, because you can use memory-mapped files (ala Unix's mmap) for them. -- John Werner john_werner@taligent.com Taligent, Inc. +++++++++++++++++++++++++++ >From sw@network-analysis-ltd.co.uk (Sak Wathanasin) Date: Sat, 12 Mar 94 09:25:50 GMT Organization: Network Analysis Ltd In article (comp.sys.mac.programmer), rang@winternet.mpls.mn.us (Anton Rang) writes: > In article platypus@cirrus.som.cwru.edu (Gary Kacmarcik) writes: > >while i agree that handles are useful. pointers _can_ be resizable. > > [ ... example of re-allocating pointers, pass in ptr, pass out ptr ... ] > > The problem with re-allocating a pointer using such a routine is > that it doesn't update any *other* pointers to the same memory block. > So if you have a data structure whose size needs to change, you need > to track every pointer to it. At that point, you're just re-inventing > handles. > -- > Anton Rang (rang@winternet.mpls.mn.us) And, of course, it's considered an "advanced C++ idiom"* these days to use ptrs to objects that may not actually be there. Variously known as smart pointers, envelopes &c (yes, I know they are not exactly the same), they can used to implement persistent objects, smart memory allocation and deallocation, bounds checking on access and so on. Mac OS handles are a special case of these. Anyone remember Iliffe's "Basic machine"? (That's "basic" as in "fundamental", not "BASIC" as in "programming language".) Mostly a paper design, but some of the ideas were implemented in the Burroughs Algol engines. And capability-based systems? The "descriptor registers" in ICL 2900/MU5 architectures? (Oh dear! showing my age :-) The more things change,... * Coplien: Advanced C++ Programing Styles and Idioms Alger: "C++ for gurus" in latest issue of Frameworks Sak Wathanasin Network Analysis Limited 178 Wainbody Ave South, Coventry CV3 6BX, UK Internet: sw@network-analysis-ltd.co.uk uucp: ...!uknet!nan!sw AppleLink: NAN.LTD Phone: (+44) 203 419996 Mobile:(+44) 850 587411 Fax: (+44) 203 690690 +++++++++++++++++++++++++++ >From peirce@outpost.SF-Bay.org (Michael Peirce) Date: Sat, 12 Mar 94 09:31:56 PST Organization: Peirce Software, Inc. platypus@cirrus.som.cwru.edu (Gary Kacmarcik) writes: >while i agree that handles are useful. pointers _can_ be resizable. >for example, the following routine: >int ReallocPtr(Ptr *p,Size newSize) { > ... > return(0); > } Two problems: (1) This works OK if you have basically unlimited memory available to you. If you don't, you can easily run into a situation where you have a memory block of size N and free memory of size N and you want to increase the size of your memory block. In this case you can't allocate a new block until you deallocate your old block which you can't do. With Handles, you can move stuff around so that you can simply extend the size of your memory block. (2) I haven't seen a good way to get the size of the memory block pointed at by a pointer. Using GetHandleSize() on the Mac is quite useful. Handles aren't nirvana, but I personally don't want to give them up. -- Michael Peirce -- peirce@outpost.sf-bay.org -- Peirce Software, Inc. -- 719 Hibiscus Place, Suite 301 -- -- San Jose, California USA 95117 -- Makers of: Smoothie & -- voice: +1.408.244.6554 fax: +1.408.244.6882 -- Peirce Print Tools -- AppleLink: peirce & America Online: AFC Peirce +++++++++++++++++++++++++++ >From resnick@cogsci.uiuc.edu (Pete Resnick) Date: Sat, 12 Mar 1994 14:18:53 -0600 Organization: University of Illinois at Urbana-Champaign In article , peirce@outpost.SF-Bay.org (Michael Peirce) wrote: >(2) I haven't seen a good way to get the size of the memory >block pointed at by a pointer. Using GetHandleSize() on the >Mac is quite useful. Uh, GetPtrSize? (IM II-37, top of the page) pr -- Pete Resnick (...so what is a mojo, and why would one be rising?) Graduate assistant - Philosophy Department, Gregory Hall, UIUC System manager - Cognitive Science Group, Beckman Institute, UIUC Internet: resnick@cogsci.uiuc.edu +++++++++++++++++++++++++++ >From gurgle@netcom.com (Pete Gontier) Date: Sat, 12 Mar 1994 22:52:04 GMT Organization: cellular u9119523@sys.uea.ac.uk (Graham Cox) writes: >In the original (non C++) implementation of the THINK class library >objects WERE handles. Did the programmer care? No- the indirection was >hidden from the programmer. Upshot- easy to write syntax PLUS efficient >memory management. In C++ I believe that objects are pointers. What >difference does it make to the programmer?- none. The syntax is >identical. The code is portable. However the fragmentation problem is >still there, and presumably C++ apps either suffer as a result or have >their own memory management code. Try multiple inheritance with a handle-based object. Pass the address of an object member field to a trap which moves memory. The portability between the two schemes is *not* transparent. >Personally, though I'm very much sold on OOP, I still like and >appreciate handles, and would prefer that C++ implemented object as >handles. Me too. It must be difficult, though, as at least three compilers have failed to support it. -- Pete Gontier, CTO, Integer Poet Software; gurgle@netcom.com +++++++++++++++++++++++++++ >From gurgle@netcom.com (Pete Gontier) Date: Sat, 12 Mar 1994 22:53:23 GMT Organization: cellular peirce@outpost.SF-Bay.org (Michael Peirce) writes: >(2) I haven't seen a good way to get the size of the memory block >pointed at by a pointer. Using GetHandleSize() on the Mac is quite >useful. GetPtrSize works. Writing your own glue to store the size works. -- Pete Gontier, CTO, Integer Poet Software; gurgle@netcom.com +++++++++++++++++++++++++++ >From hammett@sbsu1.auckland.ac.nz (Tim Hammett) Date: 13 Mar 1994 20:15:22 GMT Organization: University of Auckland peirce@outpost.SF-Bay.org (Michael Peirce) writes: >(1) This works OK if you have basically unlimited memory >available to you. If you don't, you can easily run into a >situation where you have a memory block of size N and free memory >of size N and you want to increase the size of your memory >block. In this case you can't allocate a new block until you >deallocate your old block which you can't do. With Handles, you >can move stuff around so that you can simply extend the size of >your memory block. I'm not sure I follow you here. His routine tries a SetPtrSize() first, which will attempt to increase the size of the pointed-to block without moving it (possibly by moving relocatable stuff after the block). He only copies if SetPtrSize() can't do its stuff. This is exactly the same as what would happen if you were trying to resize a handle (except SetHandleSize() will move your block if it can't resize in situ). The only objection I can see is that by using pointers exclusively, there isn't likely to be much the memory manager can do to move things out of the way to resize a block in place (because almost eveything else in the heap will be non-movable). Also Anton's point about invalid pointers was a good one. >(2) I haven't seen a good way to get the size of the memory >block pointed at by a pointer. Using GetHandleSize() on the >Mac is quite useful. There's actually a GetPtrSize() routine. (It makes sense that there should be one, since the memory manager needs to keep info about the size of blocks, even if they're non-relocatable, so that it can walk the heap). (As for stuff allocated using malloc(), that's another story). -- Tim Hammett, School of Biological Sciences, Auckland University, New Zealand. t.hammett@auckland.ac.nz Phone: +64-9-373-7599 x8365 FAX: +64-9-373-7416 +++++++++++++++++++++++++++ >From sew@design.canberra.edu.au (Simon Ward) Date: Mon, 14 Mar 94 03:58:51 GMT Organization: University of Canberra In article John Norstad, j-norstad@nwu.edu writes: >SetHandleSize(h, GetHandleSize(h) + n) is one of my favorite lines of C on >the Mac, and is one of the many reasons I find programming the Mac to be >much more fun and pleasant than programming other kinds of computers. I agree, it's a very flexible way of dealing with a user's data structures that are of an indeterminate size. Pointers can't offer the same flexiblity. Simon Ward sew@design.canberra.edu.au +++++++++++++++++++++++++++ >From ivanski@world.std.com (Ivan M CaveroBelaunde) Date: Mon, 14 Mar 1994 15:40:35 GMT Organization: The World Public Access UNIX, Brookline, MA peirce@outpost.SF-Bay.org (Michael Peirce) writes: >platypus@cirrus.som.cwru.edu (Gary Kacmarcik) writes: >>for example, the following routine: >>int ReallocPtr(Ptr *p,Size newSize) { >> ... >> return(0); >> } >Two problems: > ( ... deleted ...) Additionally, this also presents the same problem that the concept of master pointers in handles were intended to solve - namely, that the block of memory could be moved but the number the program used to identify that (the handle) need not change. If I hand off the above pointer to some other block of my program and then call ReallocPtr, the other block is left holding a reference to a stale pointer, something that does not happen with handles. -Ivan - - Ivan Cavero Belaunde (ivanski@world.std.com) Avid VideoShop Project Lead Avid Technology, Inc. +++++++++++++++++++++++++++ >From ldo@waikato.ac.nz (Lawrence D'Oliveiro, Waikato University) Date: 14 Mar 94 17:37:10 +1300 Organization: University of Waikato, Hamilton, New Zealand In article <199403082216.RAA07098@wolverine.cs.rochester.edu>, Brad Miller writes: > > Handles shouldn't be needed with any "real" VM. > Gee, and after all the comments from people pointing out how useful handles are for creating resizable objects. How does virtual memory help deal with this? Lawrence D'Oliveiro fone: +64-7-856-2889 Info & Tech Services Division fax: +64-7-838-4066 University of Waikato electric mail: ldo@waikato.ac.nz Hamilton, New Zealand 37^ 47' 26" S, 175^ 19' 7" E, GMT+13:00 +++++++++++++++++++++++++++ >From ldo@waikato.ac.nz (Lawrence D'Oliveiro, Waikato University) Date: 14 Mar 94 17:59:05 +1300 Organization: University of Waikato, Hamilton, New Zealand In article , platypus@cirrus.som.cwru.edu (Gary Kacmarcik) reminds everyone about SetPtrSize. Sure, this call exists. But how often is it likely to succeed? I can't imagine the Memory Manager deliberately goes about leaving gaps between successively- allocated blocks. Thus, it seems to me it's going to fail on the vast majority of calls. Your sample code did check for this situation, and if the pointer resize failed, it allocated a new block and deallocated the old one. Now, what happens if you have several bits of code wanting access to the data? Answer: you must maintain a single master pointer to the block. What if the clients don't know where the master pointer is? Answer: you give them a pointer to the master pointer. Congratulations! You've just reinvented handles, only you're not going to do it as efficiently as the Memory Manager can. Lawrence D'Oliveiro fone: +64-7-856-2889 Info & Tech Services Division fax: +64-7-838-4066 University of Waikato electric mail: ldo@waikato.ac.nz Hamilton, New Zealand 37^ 47' 26" S, 175^ 19' 7" E, GMT+13:00 +++++++++++++++++++++++++++ >From rabeet@aol.com (Rabeet) Date: 14 Mar 1994 23:48:03 -0500 Organization: America Online, Inc. (1-800-827-6364) Here's a simple solution to the argument: sit down, learn how to deal with handles and what they are really good for. End of argument. I have long since given up on handles for C++ objects (love mix-ins and embedded objects), which aren't of variable size anyway, but anyone doing serious Mac development uses them for a large portion of everything else. Edward Harp Rocket Science Games, Inc. Disclaimer: my opinions aren't rocket science +++++++++++++++++++++++++++ >From nagle@netcom.com (John Nagle) Date: Tue, 15 Mar 1994 17:45:08 GMT Organization: NETCOM On-line Communication Services (408 241-9760 guest) ldo@waikato.ac.nz (Lawrence D'Oliveiro, Waikato University) writes: >In article <199403082216.RAA07098@wolverine.cs.rochester.edu>, Brad Miller writes: >> >> Handles shouldn't be needed with any "real" VM. >> Handles would be more useful if they were properly supported in compilers. Many Mac compilers dereference handles without locking them, which is dumb. This started with Pascal, where "with" statements dereference handles, and you're supposed to know that you have to lock them before doing a "with" statement, unless you're sure the clauses of the "with" statement can't move memory. It got worse in C++, where there's the possibility that someone may subclass a function previously "safe" with regard to moving memory and make it unsafe. There's also a serious problem with handle objects that contain non-handle objects with constructors; SC++ will call a constructor for a subobject with the main object dereferenced and unlocked. If the compiler does a dereference on its own, the compiler should lock, unless the compiler can optimize out the lock because the intervening code is safe. The other big mistake is that Apple publishes a list of system calls that can move memory, and changes it periodically. They should have published a short list of system calls that they guarantee DON'T move memory, and never removed any. John Nagle --------------------------- >From rwparker@netcom.com (Richard W. Parker) Subject: Writing To Screen Memory Date: Mon, 28 Feb 1994 23:25:20 GMT Organization: NETCOM On-line Communication Services (408 241-9760 guest) Does anyone know of a "generally-accepted" method for writing directly to screen memory? I am looking for a method that will work across most of the 32-bitQD Macintoshes. Also - what are the pros and cons in doing so? Is CopyBits fast enough not to worry about it? -- rwparker@netcom.com +++++++++++++++++++++++++++ >From mssmith@afterlife.ncsc.mil (M. Scott Smith) Date: Tue, 1 Mar 1994 00:55:36 GMT Organization: The Great Beyond In article rwparker@netcom.com (Richard W. Parker) writes: >Does anyone know of a "generally-accepted" method for writing directly to >screen memory? I am looking for a method that will work across most of the >32-bitQD Macintoshes. > >Also - what are the pros and cons in doing so? Is CopyBits fast enough not >to worry about it? Whew boy.. There is a "generally-accepted" method of writing directly to screen memory. There was a pretty good article on this issue in a past issue of Develop. (I forget which one.. Hopefully someone remembers; you can download Develop from ftp.apple.com.) As I recall, there's a few things to keep in mind. First, you need to make as few assumptions as possible about the video hardware. If your monitor is 640x480 and your video card can only drive it at 8-bits, you can't assume that there's 640 bytes of RAM per scan line, for example. There might be a WHOLE kilobyte -- or more -- or less -- who knows? So you poll the video hardware to find the rowBytes, and use that as a basis for calculations. Also, it seems you need to make sure you're in 32-bit mode for everything to work properly. There's a hack way to "jump" to 32-bit mode right before you do any drawing and then jump back, if required. (That's pretty dangerous, so you make sure you do it when the Mac's not looking..) And there's some magic with ShieldCursor() calls (which I forget off the top of my head) which "ensure" compatibility with certain third party devices, notably the Radius Pivot monitor. Without telling us what your needs are, it's difficult to assess whether or not CopyBits is quick enough for your application, but the safe answer is "yes, it is." CopyBits is unbelievably versatile and fast. In fact, many of the QuickDraw routines are -- such as LineTo. The trick to unleashing the full power (in terms of speed) in QuickDraw is pretty well documented, I believe it was the subject of an Apple technote. (I.. forget which one. Aren't I helpful today?) You do things like make sure source and destination rectangles are equal (so VERY expensive scaling won't occur) and are divisible by 4, etc. Some people have written replacements for CopyBits which are quicker (but less versatile). What are the advantages and disadvantages of messing around with the video RAM? Disadvantages: - Many programmers will frown upon you and say "Tsk, tsk." - You may not need to for speed, anyway. - You're playing with a loaded gun in terms of ensuring compatibility with future Macs. - You've got to take it upon yourself to deal with all kinds of yechy "possibilities" that QuickDraw normally handles for you (such as.. the Radius Pivot.) - You give up the Mac interface, unless you're really tricky. For example, you won't be drawing in a window, so the user can't move your drawing across the screen... or from one monitor to another.. And System 7 doesn't know about your drawing so it's perfectly happy to throw stuff right on top of it. - Did I mention all those yechy possibilities? What if the depth of the monitor somehow gets changed in the middle of your program? Youch. - It's very low-level and a headache. You'll be rebooting quite frequently as you try to figure it out. In Quickdraw, if you write outside the boundary of a window, it's nicely clipped for you. Nothing bad happens. If you're writing to video RAM and you go off the screen, well, the best you can hope for is an exciting crash instead of a silent freeze. Advantages: - Many other programmers will congratulate you for ignoring the wimps who say "tsk, tsk." - If you know what you're doing, you can see some serious speed in certain circumstances. - Hey, a lot of people do it. Lots of games. Lots of commercial programs. Heck, even System 7 does it! - Enough people have done it to come up with a list of "rules" to follow; it's not black magic as it once used to be. (Again, find that Develop article.) - It will give you an opportunity to really understand what's going on with the video in your Mac. And I get a pleasure out of refining my code to make it quicker and quicker. It's fun to develop methods for masking, etc. You gain speed by writing routines specific to your needs. While CopyBits will do just about anything, you might find youself writing 10 different versions for different situations. - It will work with the PowerPC, so you're safe for now. - All that rebooting will let you see that friendly smiling Mac more times a day. I suppose I might get around to posting a simple class I wrote in C++ that let's you attack direct-screen drawing in a slightly less intimidating manner, on alt.sources.mac. But I must admit right now I'm not doing the 32-bit or ShieldCursor tricks. Heck, I don't need to. Works fine on my Mac right now.. So I'd need to clean it up a bit first. Good luck! Scott - - M. Scott Smith (mssmith@afterlife.ncsc.mil || umsmith@mcs.drexel.edu) Macintosh developer, student, ski bum. Eater of Cinnamon Toast Crunch. "Last stop for fuel on the information superhighway." +++++++++++++++++++++++++++ >From jwbaxter@olympus.net (John W. Baxter) Date: Mon, 28 Feb 1994 22:15:19 -0800 Organization: Internet for the Olympic Peninsula In article , rwparker@netcom.com (Richard W. Parker) wrote: > Does anyone know of a "generally-accepted" method for writing directly to > screen memory? I am looking for a method that will work across most of the > 32-bitQD Macintoshes. > > Also - what are the pros and cons in doing so? Is CopyBits fast enough not > to worry about it? I don't think this is the time to be exploring direct writing to screen memory. Too much is happening "real soon now": (1) powerPC, and (2) more important here, QuickDraw GX. The time spent mastering direct writing can probably be better spent learning QD GX (even though the latter won't be in every Mac for a while). -- John Baxter Port Ludlow, WA, USA [West shore, Puget Sound] jwbaxter@pt.olympus.net +++++++++++++++++++++++++++ >From d88-jwa@mumrik.nada.kth.se (Jon Wätte) Date: 1 Mar 1994 19:20:51 GMT Organization: Royal Institute of Technology, Stockholm, Sweden >> Does anyone know of a "generally-accepted" method for writing directly to >> screen memory? I am looking for a method that will work across most of the >> 32-bitQD Macintoshes. >I don't think this is the time to be exploring direct writing to screen >memory. Too much is happening "real soon now": (1) powerPC, and (2) more >important here, QuickDraw GX. None of these will impact direct-to-screen-drawing in the near future. If you mean the PowerPC will be fast enough to not need direct-to-screen (and the same for QDGX) then consider the large installed base of Performas which will NOT be PowerPC upgraded anytime soon, and QDGX will not be faster than QD for bitmap-type things, just better :-) >The time spent mastering direct writing can probably be better spent >learning QD GX (even though the latter won't be in every Mac for a while). Not if what he wants to do is write an arcade game. -- -- Jon W{tte, h+@nada.kth.se, Mac Hacker Deluxe -- "Don't use the Layer Manager" +++++++++++++++++++++++++++ >From ingemar@lysator.liu.se (Ingemar Ragnemalm) Date: Fri, 4 Mar 1994 10:52:11 GMT Organization: (none) mssmith@afterlife.ncsc.mil (M. Scott Smith) writes: > What are the advantages and disadvantages of messing around with the >video RAM? >Disadvantages: > - Many programmers will frown upon you and say "Tsk, tsk." > - You may not need to for speed, anyway. For games, we generally do. > - You're playing with a loaded gun in terms of ensuring compatibility with > future Macs. > - You've got to take it upon yourself to deal with all kinds of yechy > "possibilities" that QuickDraw normally handles for you (such as.. the > Radius Pivot.) An option to use it or use QuickDraw instead isn't too bad. It's hard for the program to tell if it will work, but at least the user can make it work if he/she has hardware where it doesn't. > - You give up the Mac interface, unless you're really tricky. For example, > you won't be drawing in a window, so the user can't move your drawing > across the screen... or from one monitor to another.. And System 7 > doesn't know about your drawing so it's perfectly happy to throw stuff > right on top of it. That means only a few drawbacks. Make the window non-moveable, and only use the direct-to-screen routines when it's the front window. > - Did I mention all those yechy possibilities? What if the depth of > the monitor somehow gets changed in the middle of your program? Youch. Did anyone notice how SAT switches depth automatically? :-) > - It's very low-level and a headache. This is *true*. :-( >Advantages: (Deleted - but speed is what counts) -- - - Ingemar Ragnemalm, PhD Image processing, Mac shareware games E-mail address: ingemar@isy.liu.se or ingemar@lysator.liu.se --------------------------- >From Tony Andreoli Subject: dirIDs Date: Wed, 9 Mar 1994 15:23:21 GMT Organization: Naval Air Warfare Center - Weapons Division Here is my question...I am in the home folder of an application and I know the name of a folder in the same directory. How can I obtain the dirID of the directory so that I can do a PBGetCatInfo on that directory. thanx for the help... +++++++++++++++++++++++++++ >From Steve Bryan Date: Mon, 14 Mar 1994 16:23:54 GMT Organization: Sexton Software In article Tony Andreoli, Tony_Andreoli_-_CTA@CL_63SMTP_GW.CHINALAKE.NAVY.MIL writes: >Here is my question...I am in the home folder of an application and I >know the name of a >folder in the same directory. How can I obtain the dirID of the >directory so that I can do >a PBGetCatInfo on that directory. When your program is starting up call CurResFile to identify the refNum of the resource fork of your application. Call PBGetFCBInfo with ioRefNum set to your resource fork refNum and ioFCBIndx set to zero. It will return a bunch of info including the parID for the folder containing your application. Note that there is at least one other method for obtaining the refNum of your application which may be less likely to break which is a call to GetAppParms. I mentioned the other way because that is what I use. --------------------------- >From jaeger@kunikpok.icus.com (Jaeger) Subject: jGNEFilter Q Date: Fri, 11 Mar 94 10:56:26 CST Organization: Kunikpok Kennels and Komputers (Pet Project) HereUs a question for any jGNEFilter gurus out there: Is there any time that it is safe for a jGNEFilter to uninstall itself? For instance, if the value stored in the global jGNEFilter is equal to your own entry point is it safe to uninstall yourself. Also, is it safe for an init to install a jGNEFilter at other than init time? If you do that will it be removed by the finder when the app that was running when the filter was installed quits? IUm assuming that the finder maintains the jGNEFilter global as part of the lo-mem world that is alterred when the context is switched. Brian Stern :-{)} Jaeger@fquest.com +++++++++++++++++++++++++++ >From gurgle@netcom.com (Pete Gontier) Date: Fri, 11 Mar 1994 23:31:13 GMT Organization: cellular jaeger@kunikpok.icus.com (Jaeger) writes: >HereUs a question for any jGNEFilter gurus out there: Is there any time >that it is safe for a jGNEFilter to uninstall itself? For instance, if >the value stored in the global jGNEFilter is equal to your own entry >point is it safe to uninstall yourself. Maybe. Assuming no one is trying to trick you with a skanky hack. >Also, is it safe for an init to install a jGNEFilter at other than init >time? >From what I hear on the net, it is even safe for an application to install a jGNEFilter -- and it will apply to all apps. Of course, the difficult part for an application is how to uninstall the filter when quitting. >If you do that will it be removed by the finder when the app that was >running when the filter was installed quits? No. >IUm assuming that the finder maintains the jGNEFilter global as part of >the lo-mem world that is alterred when the context is switched. >From what I have heard on the net, this is not the case. -- Pete Gontier, CTO, Integer Poet Software; gurgle@netcom.com +++++++++++++++++++++++++++ >From urge@mcl.ucsb.edu (Scott Bronson) Date: 12 Mar 1994 00:53:47 GMT Organization: University of California, Santa Barbara In jaeger@kunikpok.icus.com (Jaeger) writes: >HereUs a question for any jGNEFilter gurus out there: Is there any time >that it is safe for a jGNEFilter to uninstall itself? For instance, if >the value stored in the global jGNEFilter is equal to your own entry >point is it safe to uninstall yourself. Theoretically, once you've stored a value in JGNEFilter, you can never go back. While it's probably 99.9999% safe to deinstall your jGNE, I personally would not (and did not). Instead, I've installed a tiny, locked code resource in the Sytem Heap that would communicate with a Gestalt selector to indicate what it should do with the incoming events. Using a jGNE/Gestalt tandem also means you only have to install once, because you can use it from then on (it's immune to application launches, quits, ...) Please note: each installed jGNE slows down the machine's perceived speed--it will take longer between the time the user clicks the mouse and the button highlights. The Mac is already slower than other machines in this respect, so *please* do as little processing as possible at jGNE time. >Also, is it safe for an init to >install a jGNEFilter at other than init time? If you do that will it be >removed by the finder when the app that was running when the filter was >installed quits? IUm assuming that the finder maintains the jGNEFilter >global as part of the lo-mem world that is alterred when the context is >switched. Yes, it is safe to install a jGNE after INIT time. Just make sure to install your proc in the System Heap because it will never be uninstalled (except perhaps by you, which is bad for reasons previously mentioned). The jGNE will be called for EVERY event, not just events that belong to the application that installed it. This is a very effecitve way of slurping events destined for other apps; I've used this technique before. A low-level debugger and some patience are all that's required. Have fun with it. - Scott +++++++++++++++++++++++++++ >From moofster@world.std.com (A Happy Dog-Cow) Date: Sat, 12 Mar 1994 09:32:08 GMT Organization: The Nest of the Moofster In general, if TrapAddress(patchedTrap/Vector) == (yourHandler) Then it's safe to de-install. With very few exceptions, this is the case for all traps & low-memory vectors. I ditto earlier comments about keeping gneFilter processing to an absolute minimum. Robert M. Seretny, Armesti Research +++++++++++++++++++++++++++ >From jlscott@tigr.org (John L. Scott) Date: 15 Mar 1994 11:17:28 -0600 Organization: Self In article , jaeger@kunikpok.icus.com (Jaeger) wrote: > I'm assuming that the finder maintains the jGNEFilter > global as part of the lo-mem world that is alterred when the context is > switched. Don't assume that. jGNEFilter is _not_ altered when the context is switched. --John --------------------------- >From cverret@vnet3.vub.ac.be (Chris Verret) Subject: password encryption Date: Tue, 08 Mar 1994 15:54:07 +0100 Organization: Vrije Universiteit Brussel I suppose most users would appreciate it when an application encrypts passwords before they are placed in a preference file. So does anyone perharps know where I can find a straightforward snippet for encryption/decryption of passwords? PS: recently some queries were posted concerning the bulleting of password textitems. Its very simple to write a short filter for this. If anyone is still needs this, I'm always prepared to mail a short example. -- __________________________________________________________________________ Chris Verret cverret@vnet3.vub.ac.be +++++++++++++++++++++++++++ >From zobkiw@datawatch.com (joe zobkiw) Date: Wed, 9 Mar 1994 14:40:09 GMT Organization: Datawatch Corporation In article , cverret@vnet3.vub.ac.be (Chris Verret) wrote: > I suppose most users would appreciate it when an application > encrypts passwords before they are placed in a preference file. > > So does anyone perharps know where I can find a straightforward > snippet for encryption/decryption of passwords? This code is from NewsWatcher...it works nicely... /*---------------------------------------------------------------------------- ScramblePassword Scrambles (and unscrambles) saved passwords. This is not really secure, just something to foil people browsing using disk editors. Entry: pw = the password. len = length of password. Exit: Each byte nibble-swapped and bit-flipped. - --------------------------------------------------------------------------*/ void ScramblePassword(unsigned char *password, short len) { unsigned char *p, *pEnd; pEnd = password + len; for (p = password; p < pEnd; p++) *p = (((*p >> 4) & 0x0f) | ((*p & 0x0f) << 4)) ^ 0xff; } ___________________________________________________________ _/_/_/_/ Joe Zobkiw ,,, _/ Senior Software Engineer - - _/ Datawatch Corporation L _/_/_/_/ zobkiw@datawatch.com - +++++++++++++++++++++++++++ >From sholmes@netrix.com (Stephen R Holmes) Date: Fri, 11 Mar 1994 17:03:32 GMT Organization: Netrix Corporation In article , cverret@vnet3.vub.ac.be (Chris Verret) wrote: > I suppose most users would appreciate it when an application > encrypts passwords before they are placed in a preference file. > > So does anyone perharps know where I can find a straightforward > snippet for encryption/decryption of passwords? Actual _encryption_ may not really be necessary; encryption sort of implies that you'll want to recover the original value from the encrypted result. For passwording, all you really [may] want is to verify that the entered password is the same as the original; to do so with reasonable assurance, it may only be necessary to "hash" the original password, then "hash" all subsequent entries to see if the hash-value is the same as the one stored. Simple example: unsigned long hash_pwd (char *pwd) { unsigned long hash = 0x31415926; while (*pwd) hash = (hash<<1) + *pwd++; return (hash); } The mathematically-inclined out there may be able to tell us what the probability of two distinct passwords having the same hash-value is, but the intuitive answer is 'pretty darn small' :-) Naturally, your routine would refuse to accept 1- or 2-character passwords... /srh -- Stephen R. Holmes | sholmes@netrix.com | the usual disclaimers Netrix Corporation | srh@netrix.com | ..... Herndon, VA USA | srholmes@aolcom | witty saying TBD --------------------------- End of C.S.M.P. Digest **********************