home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Mac Game Programming Gurus / TricksOfTheMacGameProgrammingGurus.iso / Information / CSMP Digest / volume 1 / csmp-v1-186.txt < prev    next >
Encoding:
Text File  |  1994-12-08  |  46.9 KB  |  1,237 lines  |  [TEXT/R*ch]

  1. C.S.M.P. Digest             Sat, 17 Oct 92       Volume 1 : Issue 186
  2.  
  3. Today's Topics:
  4.  
  5.     Release 0.5 of Caml Light, an implementation of the ML language
  6.     OpenSelection Code (pascal source)
  7.     EditText items larger than 255 bytes?
  8.     Adding menus to existing applications (a la Thunder)
  9.     Game Techniques (was: NON-QUICKDRAW GAMES)
  10.  
  11.  
  12.  
  13. The Comp.Sys.Mac.Programmer Digest is moderated by Michael A. Kelly.
  14.  
  15. The digest is a collection of article threads from the internet newsgroup
  16. comp.sys.mac.programmer.  It is designed for people who read c.s.m.p. semi-
  17. regularly and want an archive of the discussions.  If you don't know what a
  18. newsgroup is, you probably don't have access to it.  Ask your systems
  19. administrator(s) for details.  (This means you can't post questions to the
  20. digest.)
  21.  
  22. Each issue of the digest contains one or more sets of articles (called
  23. threads), with each set corresponding to a 'discussion' of a particular
  24. subject.  The articles are not edited; all articles included in this digest
  25. are in their original posted form (as received by our news server at
  26. cs.uoregon.edu).  Article threads are not added to the digest until the last
  27. article added to the thread is at least one month old (this is to ensure that
  28. the thread is dead before adding it to the digest).  Article threads that
  29. consist of only one message are generally not included in the digest.
  30.  
  31. The entire digest is available for anonymous ftp from ftp.cs.uoregon.edu
  32. [128.223.8.8] in the directory /pub/mac/csmp-digest.  Be sure to read the
  33. file /pub/mac/csmp-digest/README before downloading any files.  The most
  34. recent issues are available from sumex-aim.stanford.edu [36.44.0.6] in the
  35. directory /info-mac/digest/csmp.  If you don't have ftp capability, the sumex
  36. archive has a mail server; send a message with the text '$MACarch help' (no
  37. quotes) to LISTSERV@ricevm1.rice.edu for more information.
  38.  
  39. The digest is also available via email.  Just send a note saying that you
  40. want to be on the digest mailing list to mkelly@cs.uoregon.edu, and you will
  41. automatically receive each new issue as it is created.  Sorry, back issues
  42. are not available through the mailing list.
  43.  
  44. Send administrative mail to mkelly@cs.uoregon.edu.
  45.  
  46.  
  47. -------------------------------------------------------
  48.  
  49. From: Xavier.Leroy@inria.fr (Xavier Leroy)
  50. Subject: Release 0.5 of Caml Light, an implementation of the ML language
  51. Date: 11 Sep 92 15:58:05 GMT
  52. Organization: INRIA Rocquencourt, France
  53.  
  54. Caml Light is a small, portable implementation of the ML language,
  55. that runs on most Unix machines. It has also been ported to the
  56. Macintosh and to the IBM PC.
  57.  
  58. Caml Light implements the Caml language, a functional language from
  59. the ML family. Caml is quite close to Standard ML, though not strictly
  60. conformant. There are some slight differences in syntax and semantics,
  61. and major differences in the module system (these changes were
  62. required to support separate compilation).
  63.  
  64. The Caml Light implementation is mature and robust enough to be fully
  65. bootstrapped, yet the whole system is quite small (about 100K for the runtime
  66. system, and another 100K of bytecode for the compiler; 1.5 megabyte of
  67. memory is enough to recompile the whole system), and easy to port to
  68. almost any 32-bit platform. 
  69.  
  70. Caml Light comes in two flavors: a classical, interactive, toplevel-based
  71. system; and a standalone, batch-oriented compiler that produces standalone
  72. programs, in the spirit of the Unix cc compiler.
  73.  
  74. The version 0.5 of the Caml Light system has been released, and is
  75. available by anonymous FTP from:
  76.  
  77.         host:      nuri.inria.fr (128.93.1.26)
  78.  
  79.         directory: lang/caml-light
  80.  
  81.         files:     cl5unix.tar.Z       Complete source code for Unix
  82.                                        machines, plus a bootstrap compiler.
  83.  
  84.                    cl5docps.Z          Compressed Postscript for the
  85.                                        Caml Light documentation (290 pages).
  86.  
  87.                    cl5docdvi.tar.Z     Compressed DVI (with Postscript
  88.                                        inserts) for the Caml Light
  89.                                        documentation (290 pages).
  90.  
  91.                    cl5macbin.sea.hqx   Binaries for the Macintosh version.
  92.  
  93.                    cl5pc386bin.zip     Binaries for the 80386 PC version.
  94.  
  95.                    cl5pc86bin.zip      Binaries for the 8086 PC version.
  96.  
  97.                    cl5macsrc.sea.hqx   Source code for the Macintosh version.
  98.  
  99.                    cl5pc386src.zip     Source code for the 80386 PC version.
  100.  
  101.                    cl5pc86src.zip      Source code for the 8086 PC version.
  102.  
  103.  
  104. The Unix version should work on any modern workstation. We have tested
  105. it on Sun 3 and 4, DecStations, HP 9000/700 and 9000/350, IBM RS/6000,
  106. SGI Indigo, Sony News, Next cubes, and some more exotic machines.
  107.  
  108. The Macintosh version is now a standalone Macintosh application, and
  109. no longer requires the Macintosh Programmer's Workshop. (Well, at
  110. least for the toplevel environment; the batch compilers still run
  111. under MPW.) The application provides some graphics primitives.
  112.  
  113. The PC version still comes in two flavors, one that run on any PC, but
  114. is severely limited by the 640K barrier, and one that run on 80386 or
  115. 80486 PC's in 32 bit protected mode to circumvent these limitations.
  116. Both versions now provide the same graphics primitives as the
  117. Macintosh version.
  118.  
  119. Ports to OS/2 and to the Amiga are in progress.
  120.  
  121. MAIN IMPROVEMENTS IN THIS RELEASE:
  122.  
  123. * Much more documentation. There's now a reference manual for the
  124. language, and a complete description of the commands. The tutorial has
  125. been extended, too.
  126.  
  127. * Language extensions: streams and stream parsers, a la Mauny/de
  128. Rauglaudre.
  129.  
  130. * Extensions to the environment: a general mechanism to link Caml
  131. Light code with C code. An X-windows toolkit based on this mechanism
  132. should be released soon. A new command, camllibr, to build libraries
  133. of Caml Light object files. A new command, camlmktop, to construct
  134. custom toplevel systems.
  135.  
  136. * Bug fixes: many of them.
  137.  
  138. * Implementation changes: a new garbage collector. The major collector
  139. is now incremental, meaning that garbage collection is even less
  140. disruptive than before. Many minor optimizations in the compiler
  141. back-end. The linker has been completely reworked, and is now clever
  142. enough to avoid linking in useless code.
  143.  
  144. * For the PC versions: line editing is supported. The 80386 port is
  145. VCPI-compliant.
  146.  
  147. FEEDBACK:
  148.  
  149. Please send your questions and comments to the Caml mailing list:
  150.  
  151.                 caml-list@margaux.inria.fr
  152.  
  153. To subscribe or unsubscribe to the list, mail to
  154. caml-list-request@margaux.inria.fr.
  155.  
  156.  
  157. - - Xavier Leroy
  158.  
  159. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  160. % The Caml Light racing team, projet Formel, INRIA Rocquencourt.     %
  161. % "Low tar, Caml taste".                                             %
  162. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  163.  
  164. ---------------------------
  165.  
  166. From: mxmora@unix.sri.com (Matthew Xavier Mora)
  167. Subject: OpenSelection Code (pascal source)
  168. Date: 11 Sep 92 17:11:08 GMT
  169. Organization: SRI International
  170.  
  171.  
  172. Here's the code to have the finder open a control panel.
  173. Just pass the control panel's fsspec to the openselection
  174. function and it should open it. Actually I think it will
  175. open any valid fsspec but I wouldn't bet on it. I haven't
  176. stressed this code so there are probably some bugs in it.
  177.  
  178. Matt
  179.  
  180. - --------------------------------------------
  181. { OpenSelection.p ported by Matthew Xavier Mora} 
  182. { ported from C.K. Han's openselection.c code  }
  183. { 09-11-92                                     }
  184.  
  185. unit openSelection; 
  186. interface
  187.   uses
  188.     AppleTalk, PPCToolBox, Processes, EPPC, Notification, AppleEvents,
  189.     {, Errors, Events, Memory, Resources, SegLoad, }
  190.  
  191.     (* Group 3 *)
  192.     Aliases {, thermometer};
  193.  
  194.   function OpenSelection (var theFileToOpen: FSSpec): OSErr;
  195.  
  196. implementation
  197.   const
  198.     kFinderType = 'FNDR';
  199.     kSysCreator = 'MACS';
  200.     kAEOpenSelection = 'sope';
  201.     aeSelectionKeyword = 'fsel';
  202.  
  203. { This runs through the process list looking for the indicated application
  204. }
  205.   function FindAProcess (typeToFind, creatorToFind: Ostype;
  206.                          var processSN:ProcessSerialNumber;
  207.                          var infoRecToFill: ProcessInfoRec): OSErr;
  208.     var
  209.       tempPSN: ProcessSerialNumber;
  210.       myErr: OSErr;
  211.  
  212.   begin
  213.     myErr := noErr;
  214.     tempPSN.lowLongOfPSN := kNoProcess;
  215.     processSN.lowLongOfPSN := kNoProcess;
  216.     processSN.highLongOfPSN := kNoProcess;
  217.     repeat
  218.       begin
  219.         myErr := GetNextProcess(processSN);
  220.         if (myErr = noErr) then
  221.           myErr := GetProcessInformation(processSN, infoRecToFill);
  222.       end;
  223.     until ((infoRecToFill.processSignature = creatorToFind) or
  224.    (infoRecToFill.processType = Longint(typeToFind)) or (myErr <> noErr));
  225.  
  226.     FindAProcess := myErr;
  227.   end;
  228.  
  229.   function OpenSelection (var theFileToOpen: FSSpec): OSErr;
  230.     var
  231.       aeEvent, aeReply: AppleEvent;
  232.       aeDirDesc, listElem: AEDesc;
  233.       interactErr: OSErr;
  234.       dirSpec, procSpec: FSSpec;
  235.       fileList: AEDesc;
  236.       myReply: StandardFileReply;
  237.       myErr: OSErr;
  238.       process: ProcessSerialNumber;
  239.       DirAlias, FileAlias: AliasHandle;
  240.       infoRec: ProcessInfoRec;
  241.       processName: Str31;
  242.       fullPath, appName: Str255;
  243.       myAddressDesc: AEDesc;
  244.   begin
  245.     interactErr := noErr;
  246.  
  247.     if (true) then
  248.       begin
  249.         infoRec.processInfoLength := sizeof(ProcessInfoRec);
  250.         infoRec.processName := @processName;
  251.         infoRec.processAppSpec := @procSpec;
  252.  
  253.         myErr := FindAProcess(kFinderType, kSysCreator, process, infoRec);
  254.         if (myErr = noErr) then
  255.           myErr := AECreateDesc(typeProcessSerialNumber, @process,
  256.                                 sizeof(process), myAddressDesc);
  257.  
  258.  
  259.         if (myErr = noErr) then
  260.           begin
  261.  
  262.             { Create the FinderEvent }
  263.             myErr := AECreateAppleEvent(kFinderType, kAEOpenSelection,
  264.                                         myAddressDesc,
  265. kAutoGenerateReturnID,
  266.                                         kAnyTransactionID, aeEvent);
  267.             { If you want to keep talking to this machine, you can keep
  268. this  }
  269.             { address desc around }
  270.             myErr := AEDisposeDesc(myAddressDesc);
  271.  
  272.             if (myErr = noErr) then
  273.               begin
  274.                 { Now we build all the bits of an OpenSelection event. }
  275.                 { Basically, we need to create an alias for the item to
  276. open,}
  277.                 { and an alias to the parent }
  278.                 { folder (directory) of that item. }
  279.                 { We can also pass a list of files if we want.  }
  280.                 { You'll notice that for opening a finder window, the file
  281. and}
  282.                 { directory alias both point at the }
  283.                 { folder itself }
  284.                 { make a spec for the parent folder }
  285.  
  286.  
  287.                 myErr := FSMakeFSSpec(theFileToOpen.vRefNum,
  288.                                       theFileToOpen.parID, '', dirSpec);
  289.                 myErr := NewAlias(nil, dirSpec, DirAlias);
  290.  
  291.                 { Create alias for file }
  292.                 { if you are opening a window, then you make the file alias
  293. the}
  294.                 { same as the dir alias }
  295.                 myErr := NewAlias(nil, theFileToOpen, FileAlias);
  296.                 interactErr := AEInteractWithUser(kAEDefaultTimeout, nil,
  297. nil);
  298.                 if (interactErr = noErr) then
  299.                   myErr := SetFrontProcess(process);
  300.  
  301.                 { Create the file  list }
  302.                 if (myErr = noErr) then
  303.                   begin
  304.                     myErr := AECreateList(nil, 0, false, fileList);
  305.  
  306.                     {  create the folder  descriptor }
  307.                     HLock(Handle(DirAlias));
  308.                     myErr := AECreateDesc(typeAlias, Ptr(DirAlias^),
  309.                                           GetHandleSize(Handle(DirAlias)),
  310.                                           aeDirDesc);
  311.                     HUnlock(Handle(DirAlias));
  312.                     myErr := AEPutParamDesc(aeEvent, keyDirectObject,
  313.                                             aeDirDesc);
  314.                     if (myErr = noErr) then
  315.                       begin
  316.                         { done with the desc, kill it }
  317.                         myErr := AEDisposeDesc(aeDirDesc);
  318.                         {  create the file descriptor and add to aliasList
  319. }
  320.                         HLock(Handle(FileAlias));
  321.                         myErr := AECreateDesc(typeAlias, Ptr(FileAlias^),
  322.                                              
  323. GetHandleSize(Handle(FileAlias)),
  324.                                               listElem);
  325.                         HLock(Handle(FileAlias));
  326.                         myErr := AEPutDesc(fileList, 0, listElem);
  327.                       end;
  328.                     if (myErr = noErr) then
  329.                       begin
  330.  
  331.                         myErr := AEDisposeDesc(listElem);
  332.  
  333.                         { Add the file alias list to the event }
  334.                         myErr := AEPutParamDesc(aeEvent,
  335. aeSelectionKeyword,
  336.                                                 fileList);
  337.                         myErr := AEDisposeDesc(fileList);
  338.  
  339.                         if (myErr = noErr) then
  340.                           myErr := AESend(aeEvent, aeReply,
  341.                                           kAENoReply + kAEAlwaysInteract + 
  342.                                           kAECanSwitchLayer,
  343.                                           kAENormalPriority,
  344. kAEDefaultTimeout,
  345.                                           nil, nil);
  346.                       end;
  347.                   end;
  348.                 myErr := AEDisposeDesc(aeEvent);
  349.               end;
  350.           end;
  351.       end;
  352.     if (DirAlias <> nil) then
  353.       DisposHandle(Handle(DirAlias));
  354.     if (FileAlias <> nil) then
  355.       DisposHandle(Handle(FileAlias));
  356.     OpenSelection := myErr;
  357.   end;
  358.  
  359. end.
  360.  
  361. ---------------------------
  362.  
  363. From: timper@iat.holonet.net (Tim Perkis)
  364. Subject: EditText items larger than 255 bytes?
  365. Date: 9 Sep 92 08:33:35 GMT
  366. Organization: HoloNet (BBS: 510-704-1058)
  367.  
  368. Is there a reasonable way to access an editText item in a Modal
  369. dialog having more than 255 Characters? I know that a Dialog
  370. Record has a normal TErecord to hold the text: the bottleneck limiting
  371. edit text dialog items to 255 seems to be the GetDItem arguments,
  372. which are Str255. 
  373.  
  374. Even better, does anyone know of a CDEF or hunk of code available to
  375. put a scrollable edit text in a dialog user or control item?
  376.  
  377. Respond by email or posting here.
  378.  
  379. timper@holonet.net
  380.  
  381. +++++++++++++++++++++++++++
  382.  
  383. From: amanda@intercon.com (Amanda Walker)
  384. Date: 9 Sep 92 21:59:09 GMT
  385. Organization: InterCon Systems Corporation, Herndon, VA
  386.  
  387. timper@iat.holonet.net (Tim Perkis) writes:
  388. > Is there a reasonable way to access an editText item in a Modal
  389. > dialog having more than 255 Characters? I know that a Dialog
  390. > Record has a normal TErecord to hold the text: the bottleneck limiting
  391. > edit text dialog items to 255 seems to be the GetDItem arguments,
  392. > which are Str255. 
  393.  
  394. Close.  TextEdit is limited to 32K, which puts a hard limit on the size of an 
  395. editable text item.  The key to getting more than 255 characters, however, is 
  396. simply to avoid using GetIText & SetIText, but to use GetDItem and SetDItem 
  397. directly, copying things into and out of thew handle yourself.
  398.  
  399.  
  400. Amanda Walker <amanda@intercon.com>
  401. - -- 
  402. "I wouldn't be surprised if the architecture of Intel's microprocessors
  403.  were eventually linked to the eventual fall of mankind."
  404.                 --Steve Gibson
  405.  
  406. +++++++++++++++++++++++++++
  407.  
  408. From: resnick@cogsci.uiuc.edu (Pete Resnick)
  409. Date: 10 Sep 92 21:07:25 GMT
  410. Organization: University of Illinois at Urbana
  411.  
  412. bpb9204@tamsun.tamu.edu (Brent) writes:
  413.  
  414. >amanda@intercon.com (Amanda Walker) writes:
  415. >|
  416. >|Close.  TextEdit is limited to 32K, which puts a hard limit on the size of an 
  417. >|editable text item.  The key to getting more than 255 characters, however, is 
  418. >|simply to avoid using GetIText & SetIText, but to use GetDItem and SetDItem 
  419. >|directly, copying things into and out of thew handle yourself.
  420.  
  421. You can't do this!
  422.  
  423. >If you have a modal dialog box with 4 text areas, that's automatically
  424. >128k of RAM sucked up for 4x255 = 1020 bytes for actualy data (retrieved or
  425. >set via the SetIText/GetIText calls.  If you used the MacOS calls to
  426. >the letter, that's a 1020/128k percent utilization... pretty awful.
  427.  
  428. No, no, no. RTFM folks. IM I-408:
  429.  
  430.         Note: Actually, a single edit record is shared by all editText
  431.         items; ...
  432.  
  433. So, first of all, you can't look in the TextEdit record to see what's
  434. in it because you won't know where in that record the field you want
  435. is stored. Second of all, the hText field of the TextEdit record is a
  436. handle to the text which changes size as you add and delete text. It
  437. is not a static 32K of data.
  438.  
  439. pr
  440. - -- 
  441. Pete Resnick             (...so what is a mojo, and why would one be rising?)
  442. Graduate assistant - Philosophy Department, Gregory Hall, UIUC
  443. System manager - Cognitive Science Group, Beckman Institute, UIUC
  444. Internet: resnick@cogsci.uiuc.edu
  445.  
  446. +++++++++++++++++++++++++++
  447.  
  448. From: stepan@natinst.com (Stepan Riha)
  449. Date: 10 Sep 92 21:20:27 GMT
  450. Organization: National Instruments, Austin, TX
  451.  
  452. In article <1992Sep10.200136.18513@tamsun.tamu.edu> bpb9204@tamsun.tamu.edu (Brent) writes:
  453.  
  454.     [how to get more than 255 chars out of a dialog text item deleted]
  455.  
  456. >Now I have a question.  When you make a new TERecord, it is 32k in size,
  457. >right?
  458. >
  459. >If you have a modal dialog box with 4 text areas, that's automatically
  460. >128k of RAM sucked up for 4x255 = 1020 bytes for actualy data (retrieved or
  461. >set via the SetIText/GetIText calls.  If you used the MacOS calls to
  462. >the letter, that's a 1020/128k percent utilization... pretty awful.
  463. >
  464. >Hey, Apple!  How about creating a new TextEdit interface so that we can
  465. >specify the buffer size to use -- as large or small as we need?
  466. >
  467. >-Brent
  468.  
  469. When you make a new TERecord you only allocate memory for a TERec which is
  470. initially a little over 100 bytes large.  The actual text is stored in a handle
  471. that grows according to how much text you have.
  472. So if your (one-line) text contains 10 characters you'll use about 130 bytes
  473. which is less than a Str255.  If you actually have 255 characters in your
  474. item, you'll need about 43% more memory than if items used Str255; with 10
  475. characters you actually save about 50%.
  476.  
  477. Of course there is the overhead for two handles but that's quite negligible.
  478.  
  479. - -- 
  480.    Stepan Riha -- stepan@natinst.com
  481.  
  482. +++++++++++++++++++++++++++
  483.  
  484. From: bpb9204@tamsun.tamu.edu (Brent)
  485. Date: 10 Sep 92 23:02:40 GMT
  486. Organization: Texas A&M Univ., Inc.
  487.  
  488. bpb9204@tamsun.tamu.edu (Brent) writes:
  489. |
  490. |Now I have a question.  When you make a new TERecord, it is 32k in size,
  491. |right?
  492.  
  493. I apologize; my brain tries really hard sometimes to take a break.
  494. I've used TextEdit stuff before and I don't know why I started thinking
  495. like the above...  No, the TERec is NOT 32k.  
  496.  
  497. - -Brent
  498.  
  499. p.s. please don't email me any more replies to the above blunder.
  500.  
  501. ---------------------------
  502.  
  503. From: korfhage@weston.poly.edu
  504. Subject: Adding menus to existing applications (a la Thunder)
  505. Date: 12 Sep 92 15:45:40 GMT
  506. Organization: Polytechnic University, New York
  507.  
  508. We have a project consisting of a number of programs that interact with a HyperCard stack. All the programs in this project are supposed to have two menus (in addition to their normal menus) - one menu lists the other programs in the project and will launch them, and the other menu sends apple events to the hypercard stack or other programs. The apple event parameters will sometimes include the name of the front window.
  509.  
  510. We have source code for some of the programs, so they are no problem to modify. For other programs, like Excel, we can add macros and external functions to get it to do what we want. However, some programs are simply not customizable to the extent that we need. For these programs, it seems that we need to do something like the Thunder spelling checker, which adds its own menu to the menubar of specific applications.
  511.  
  512. The only problem is that I am not guru enough to know how to do this. Could anyone please help me with explanation and/or pointers to example code?
  513.  
  514. Thanks ever so much!
  515.  
  516.    Willard
  517.  
  518. +++++++++++++++++++++++++++
  519.  
  520. From: haynes@mace.cc.purdue.edu (Carl W. Haynes III)
  521. Date: 12 Sep 92 17:58:22 GMT
  522. Organization: Purdue University
  523.  
  524. In article <1992Sep12.154540.15753@prism.poly.edu> korfhage@weston.poly.edu writes:
  525. >  [ asks how to add menus to existing applications ]
  526. >
  527.  
  528. I wrote an INIT awhile ago which added a menu to SimAnt (SimAnt Cheater)
  529.  
  530. What I ended up doing was tail-patching _SetMenuBar and _MenuSelect.
  531.  
  532. On SetMenuBar, I would check to see if I was dealing with SimAnt and then
  533. Create a new menu and insert it. The patch for _MenuSelect would simply
  534. check to see if my menu was selected and respond accordingly.
  535. I was only worried about making it work with this one application, I don't
  536. know how generalizable this would be to others.
  537.  
  538. If you're only dealing with system 7, I'd suggest looking into how to
  539. add icon menus, like the help and application menu, to all applications.
  540. (I think they call them Finder Menus). I believe that this years
  541. MacHack disk has a couple examples of how to do this. In fact I
  542. believe Dylan Talk (available at the usual archives and the MacHack disk) 
  543. does this also and has source code.
  544.  
  545. carl
  546.  
  547.  
  548. - --
  549. Carl W. Haynes III  
  550. Haynes Consulting Services        ||  CWH3@aol.com
  551. PO Box 2715                       ||  haynes@mace.cc.purdue.edu
  552. W. Lafayette, IN 47906            ||  hcs@applelink.apple.com
  553. - ----------------------------------------------------------------------
  554.                   Macintosh Programming & Consulting
  555.  
  556. +++++++++++++++++++++++++++
  557.  
  558. From: leonardr@netcom.com (Leonard Rosenthol)
  559. Date: Sat, 12 Sep 92 21:58:35 GMT
  560. Organization: Netcom - Online Communication Services  (408 241-9760 guest) 
  561.  
  562. In article <BuH8LA.Crq@mentor.cc.purdue.edu> haynes@mace.cc.purdue.edu (Carl W. Haynes III) writes:
  563. >In article <1992Sep12.154540.15753@prism.poly.edu> korfhage@weston.poly.edu writes:
  564. >>  [ asks how to add menus to existing applications ]
  565. >>
  566. >
  567. >I wrote an INIT awhile ago which added a menu to SimAnt (SimAnt Cheater)
  568. >
  569. >What I ended up doing was tail-patching _SetMenuBar and _MenuSelect.
  570. >
  571. >On SetMenuBar, I would check to see if I was dealing with SimAnt and then
  572. >Create a new menu and insert it. The patch for _MenuSelect would simply
  573. >check to see if my menu was selected and respond accordingly.
  574. >I was only worried about making it work with this one application, I don't
  575. >know how generalizable this would be to others.
  576. >
  577.     that's the basic idea, though I would suggest patching _DrawMenuBar
  578. instead of _SetMenuBar, since many apps don't call _SetMenuBar.  Also, if
  579. you are planning any cmdKey equivalents, then you'll need to patch
  580. _menuKey as well.
  581.  
  582. >If you're only dealing with system 7, I'd suggest looking into how to
  583. >add icon menus, like the help and application menu, to all applications.
  584. >(I think they call them Finder Menus). 
  585. >
  586.     they are called System Menus, since they are owned by the System...
  587. Which brings up a request...PLEASE DO NOT WRITE SYSTEM MENUS!!!  They require
  588. using a slew of undocumented information as well as NOT being guarenteed to
  589. work in the future (at least not the same way).  
  590.  
  591. - -- 
  592. - -----------------------------------------------------------------------------
  593. Leonard Rosenthol            Internet:     leonardr@netcom.com
  594. Director of Advanced Technology        AppleLink:    MACgician
  595. Aladdin Systems, Inc.            GEnie:        MACgician
  596.  
  597.  
  598. ---------------------------
  599.  
  600. From: jholt@adobe.com (joe holt)
  601. Subject: Game Techniques (was: NON-QUICKDRAW GAMES)
  602. Organization: Adobe Systems Inc.
  603. Date: Tue, 8 Sep 1992 00:48:21 GMT
  604.  
  605. Whoa! Slow down. All this talk of palettes is way ahead of schedule. First
  606. we've got to talk about sync'ing to monitor retrace, opening windows and
  607. positioning them on long word boundaries, and--and... Oh, what the heck.
  608.  
  609.  
  610. PALETTES
  611.  
  612. I must be honest and say I didn't know that much about the Palette Manager
  613. until this morning, when I read all of these palette questions and I asked
  614. myself, "Yeah, so how does one do that?" You see, my last serious, for
  615. profit, game endeavor was several years ago when the word on the street was
  616. that the current implementation of the Palette Manager was best avoided.
  617.  
  618. So like any good engineer, I combed the documentation for the lowest-level
  619. access to the video card's clut and used it. This information was available
  620. in the first edition of "Designing Cards and Drivers for the Macintosh
  621. Family (Starring Delta Burke)". Along with the clut calls one could find the
  622. calls for changing a monitor's depth without the pesky Monitors control
  623. panel. Of course this useful information has been removed from subsequent
  624. editions of "Designing Cards" in the interest of public safety (just like
  625. Delta Burke).
  626.  
  627. But now everything works, we've been given SetDepth(), and we should use
  628. what the system provides. And here's what I came up with this morning:
  629.  
  630. The basic strategy is to create a window "around" whatever direct-to-screen
  631. stuff you're going to do, and attach the appropriate palette to it. The
  632. window does two useful things for us: it keeps the rest of the system from
  633. drawing on top of us--that is, it sorta legitimizes our poking onto the
  634. screen (this is what I meant in the first post about screen real estate),
  635. and it gives us an easy place to hang a palette that is used whenever the
  636. window is frontmost.
  637.  
  638. So let's create the window (this code assumes an 8-bit color display and
  639. System 7):
  640.  
  641. // global stuff
  642.  
  643. #include <Palettes.h>
  644.  
  645. static WindowPtr window;
  646. static CTabHandle clut;
  647. static PaletteHandle palette;
  648.  
  649. ..
  650.  
  651. // inside initialization code
  652.  
  653.     Rect bounds;
  654.  
  655.     SetRect( &bounds, 50, 50, 512+50, 384+50 );
  656.     window = NewCWindow( nil, &bounds, "\pRed", true, noGrowDocProc,
  657.         (WindowPtr) -1, true, 0 );
  658.     SetPort( window );
  659.  
  660. And stick a palette onto it:
  661.  
  662.     clut = (CTabHandle) GetResource( 'clut', 128 );
  663.     palette = NewPalette( 32, clut, pmAnimated+pmExplicit, 0 );
  664.     SetPalette( window, palette, false );
  665.  
  666. The 'clut' resource is a ramp from white in index zero to 100% red in
  667. index 31. ResEdit has a blend command which makes this easy. Once you get
  668. this working, experiment with different values in the clut.
  669.  
  670. The flags to NewPalette() tell the Palette Manager that index zero in the
  671. clut resource should be stuck in the video card's clut at index zero, and
  672. so on (pmExplicit), and that no one else can use our colors (pmAnimated).
  673. As I read Inside Mac 6, the combination of these two makes them the highest
  674. priority as the Palette Manager is trying to shoehorn colors into the
  675. hardware clut. Basically we're saying that colors 0 through 31 belong to
  676. us and nobody else, and here they are. Nyah.
  677.  
  678. To see if all of this works, I draw a ramp of my colors into the window
  679. on update events:
  680.  
  681. // In response to update events
  682.  
  683.     int c, y;
  684.     RGBColor black;
  685.  
  686.     y = 0;
  687.     PenSize( 10, 10 );
  688.     black.red = black.green = black.blue = 0;
  689.     TextSize( 9 );
  690.  
  691.     for ( c = 0; c < 32; ++c ) {
  692.         unsigned char text[100];
  693.  
  694.         PmForeColor( c );
  695.         MoveTo( 16, y );
  696.         LineTo( 16384, y );
  697.  
  698.         RGBForeColor( &black );
  699.         MoveTo( 2, y + 9 );
  700.         NumToString( c, text );
  701.         DrawString( text );
  702.  
  703.         y += 12;
  704.     }
  705.     PenNormal();
  706.  
  707. Each line in the window lists an index (0 - 31) and shows a bar of that
  708. color. Using PmForeColor() says we want the RGB color of that particular
  709. index--which, if all this Palette Manager stuff is working, should be the
  710. value that's stored into screen memory. Hmmm... what if I just poked those
  711. values into memory myself?
  712.  
  713. // Do this on mouse downs, or whenever you want
  714.  
  715.     static int c = 0;
  716.     PixMapHandle pix;
  717.     Ptr baseAddr, rowBase, p;
  718.     int rowBytes, x, y;
  719.     char mmuMode;
  720.     Rect bounds;
  721.     unsigned char text[100];
  722.  
  723.     SetRect( &bounds, -32000, -32000, 32000, 32000 );
  724.     pix = (**GetMaxDevice( &bounds )).gdPMap;
  725.     baseAddr = (**pix).baseAddr;
  726.     rowBytes = (**pix).rowBytes & 0x3FFF;
  727.  
  728.     mmuMode = true32b;
  729.     SwapMMUMode( &mmuMode );
  730.     for ( rowBase = baseAddr, y = 30; y; --y ) {
  731.         for ( p = rowBase, x = 30; x; --x ) *p++ = c;
  732.         rowBase += rowBytes;
  733.     }
  734.     SwapMMUMode( &mmuMode );
  735.  
  736.     TextSize( 12 );
  737.     SetRect( &bounds, 485, 0, 16384, 20 );
  738.     EraseRect( &bounds );
  739.     MoveTo( bounds.left + 5, bounds.bottom - 5 );
  740.     NumToString( c, text );
  741.     DrawString( text );
  742.  
  743.     c = (c+1) % 32;
  744.  
  745. I wrote this code as my mouse down handler just to give me an easy way to
  746. trigger it. It draws a rectangle in the upper left corner of the screen by
  747. stuffing values directly into screen memory. The value it stuffs--<c>--is
  748. incremented each time this executes and the value is displayed in the upper
  749. right corner of our window.
  750.  
  751. - --> I'm using GetMaxDevice() because my main monitor is a 4-bit grayscale
  752. two-page display, and my second monitor is the 8-bit one where I want the
  753. drawing to take place. Suit to taste.
  754.  
  755. Notice that I SwapMMUMode() around the stuff that actually "draws" into
  756. screen memory. As mentioned before, this is necessary only in certain video
  757. configurations, but for now it doesn't hurt to be safe, and the alternative
  758. is death by poking.
  759.  
  760. So I run this, drag the window over to my 8-bit monitor, and I see a nice
  761. red ramp in the window, white at the top and deep red at the bottom. When I
  762. click the mouse button a white square appears in the corner of my monitor
  763. and the number '0' appears in the window. Each time I click the mouse the
  764. number increments and the square gets redder. Wow.
  765.  
  766. What have I just done? In a system-friendly way, I've forced my will upon
  767. the video hardware and blasted screen memory. I know that a zero written
  768. into screen memory will be color zero from my clut, a one will be color
  769. number one, etc. I know this because I TOLD IT.
  770.  
  771. Just to prove that the Palette Manager is really doing it's job, bring up
  772. the Monitors control panel and play with the screen depth, moving the app
  773. window from frontmost to the back and back and forth. By the way, take a look
  774. at the small clut display at the bottom of the control panel. Is the red
  775. ramp at the start where you think colors 0 - 31 should be? Wrong! The
  776. Monitors control panel shows the entries in reverse order. Go figure.
  777.  
  778. Now of course to really do this right you'd want to put the red square inside
  779. the window. Otherwise the system doesn't know we've been drawing and odd
  780. visuals result. (For example, put the window's drag bar so that it overlaps
  781. the red square and click the mouse button so that the square clobbers part of
  782. the drag bar. Then move the window.) This entails finding the screen address
  783. of the upper left corner of the *window*, and possibly aligning the window on
  784. a long word boundary. But these will have to be subjects of another post, as
  785. this one is already pushing the limits of my concentration.
  786.  
  787. /joe
  788.  
  789.  
  790. +++++++++++++++++++++++++++
  791.  
  792. From: triantos@acsu.buffalo.edu (Nick B Triantos)
  793. Date: 8 Sep 92 04:13:31 GMT
  794. Organization: The University at Buffalo
  795.  
  796. First, thanks to Joe Holt and Ben Haller, without whom I still wouldn't have a
  797. clue whether it is _really_ possible to do direct screen writes.  I do have a
  798. question or four which have arisen from building a program based on Joe's words
  799. about finding the screen memory, though.
  800.  
  801. On my Mac IIci, with a 640x480 color monitor working through a RasterOps 264
  802. card, 1K of memory is reserved for each row of screen pixels, although the
  803. monitor only uses the first 640 bytes of each 1024.  So my question is this:
  804. Is this a standard behavior for 640x480 video cards?  What about for those
  805. screens and video cards that produce 800+ pixels horizontally?  They should
  806. still fit within the 1024 bytes.  But how about the 21" monitors that provide
  807. some 1200+ pixels horizontally?  Do those cards reserve 2K / row, or am I just
  808. generalizing something which only my video card is doing?
  809.  
  810. Second, I changed the test part of the program as follows:  I did
  811. while(!Button())
  812.   *myScrnPtr++ = 0xAA
  813. and some other things.  I make sure that I hit the button before I hit the end
  814. of the screen.  Now, it seems as though the drawing is still slow (I'd say
  815. about 100 lines / sec).  Is that slowdown all because of my while(!Button())?
  816. I didn't think that that function should be so burdensome to the CPU.  Guess
  817. that's something I should try out on my own, but it can't hurt to ask.
  818.  
  819. Related to that, I guess it doesn't seem as though my little test program
  820. places values in Screen memory at anything close to the rate of, say, moving a
  821. 400x300 window.  For my example, the system would be moving ~120K bytes, and so
  822. it should go relatively quickly, but it seems really fast to me, considering it
  823. takes me almost as long to move 1200 bytes.  Is the System's window moving code
  824. optimized to move more than words at a time?  Does the 68000 have something
  825. similar to a MOVE.BLK <src>,<dst> instruction?
  826.  
  827. Last question, directed more toward Ben Haller than most others.  Does Solarian
  828. II use two screens worth of memory and switch between the two for such smooth
  829. animation?  I understand that you're not animating the whole 640x480 screen at
  830. once, but it still does look really nice and smooth.
  831.  
  832. Well, I guess that's all for now.  So long, and thanks for all the fish.
  833.  
  834. - -Nick
  835. - --
  836. Nick Triantos    internet: triantos@acsu.buffalo.edu
  837.                  AOL:      Triantos
  838. "Scientists tell us that the fastest animal on earth, with a top speed of
  839. 120 ft/sec, is a cow that has been dropped out of a helicopter." - Dave Barry
  840.  
  841. +++++++++++++++++++++++++++
  842.  
  843. From: jholt@adobe.com (joe holt)
  844. Organization: Adobe Systems Inc.
  845. Date: Tue, 8 Sep 1992 19:13:42 GMT
  846.  
  847. Nick asks some good questions. The biz about 1K per row of 640 bytes is a real shocker,
  848. isn't it? *All* of that left over memory! But that's the way it's done--it's easier in
  849. hardware to divide by 1K. You'll notice other such wastes as you go to other screen
  850. depths/configurations. Most cards do this. RAM is cheap, right?
  851.  
  852. There are three things that slow down your small screen blasting loop:
  853.  
  854. while ( !Button() )
  855.     *myScrnPtr++ = 0xAA;
  856.  
  857. #1 is that the Button() call here is a real cycle sink--altho' it's quite snappy
  858. compared to, say, CopyDeepMask() with a maskRgn. If you were to profile this code
  859. you'd see about 95% going to the Button() call. Here's how it compiles for me:
  860.  
  861.   mouse_down
  862.      +003E  00EFECF4  *BRA.S      mouse_down+0044            ; 00EFECFA   | 6004
  863.      +0040  00EFECF6   MOVE.B     #$AA,(A3)+                              | 16FC 00AA
  864.      +0044  00EFECFA   CLR.B      -(A7)                                   | 4227
  865.      +0046  00EFECFC   _Button                               ; A974       | A974
  866.      +0048  00EFECFE   TST.B      (A7)+                                   | 4A1F
  867.      +004A  00EFED00   BEQ.S      mouse_down+0040            ; 00EFECF6   | 67F4
  868.  
  869. The branch at the start is only done once to get into the while() loop, so it
  870. doesn't count. The button testing code, including the trap dispatch overhead and
  871. the actual Button() code in ROM, comes to about 300 cycles. In contrast, the *one*
  872. instruction which actually writes to the screen and increments myScrnPtr:
  873.  
  874.      +0040  00EFECF6   MOVE.B     #$AA,(A3)+                              | 16FC 00AA
  875.  
  876. Is all of 12 cycles, or just 4% of the loop. Wow. So get rid of the Button()! You
  877. could test the low-mem global MBState yourself, or make it a for loop. Do this and
  878. you'll see a blinding increase:
  879.  
  880. while ( *((char *)0x172) < 0 )  // MBState, if you didn't know...
  881.     *myScrnPtr++ = 0xAA;
  882.  
  883. Get ready to hit that mouse button!
  884.  
  885.  
  886. #2 is that you're only stuffing bytes at a time. The 680x0 is non-intuitive in that
  887. it does *not* take twice as long to write a word into memory, or four times as long
  888. to write a long. Words are just as fast as bytes. Let me repeat: whenever you store
  889. a byte, you can store a word just as fast. Gee, that makes sense, doesn't it?
  890. Whatever the reason for this quantum leap, we game programmers must take advantage
  891. of it. But wait. Long words are faster than two words, so that's what you've got
  892. to use. Change the loop above to:
  893.  
  894.     long *longPtr = (long *) myScrnPtr;
  895.  
  896.     while ( *((char *)0x172) < 0 )
  897.         *longPtr++ = 0xAAAAAAAA;
  898.  
  899. Now you're talking fast. We're also getting into that gray area where it really would
  900. be better just to code the dang thing in assembly. For example, the compiler is likely
  901. to code the 0xAAAAAAAA as an immediate operand, but if it's put into a data register
  902. the speed almost doubles. This might do it:
  903.  
  904.     long *longPtr = (long *) myScrnPtr;
  905.     long color = 0xAAAAAAAA;
  906.  
  907.     while ( *((char *)0x172) < 0 )
  908.         *longPtr++ = color;
  909.  
  910. Which in assembly looks like this:
  911.  
  912.   mouse_down
  913.      +0042  00ECA5F8  *MOVEA.L    A2,A4                                   | 284A
  914.      +0044  00ECA5FA   MOVE.L     #$AAAAAAAA,D7                           | 2E3C AAAA AAAA
  915.      +004A  00ECA600   BRA.S      mouse_down+004E            ; 00ECA604   | 6002
  916.      +004C  00ECA602   MOVE.L     D7,(A4)+                                | 28C7
  917.      +004E  00ECA604   TST.B      MBState                                 | 4A38 0172
  918.      +0052  00ECA608   BLT.S      mouse_down+004C            ; 00ECA602   | 66F8
  919.  
  920. The first three instructions are only done once, so they don't count. The loop itself--
  921. the last three instructions--is just 34 cycles. 40x faster than the original version!
  922.  
  923.  
  924. #3 is nit-picking, but it will really speed things up, too. It's pretty silly to test
  925. for a mouse down between *every* long. Do it between every ten or so:
  926.  
  927.     while ( *((char *)0x172) < 0 ) {
  928.         *longPtr++ = color;
  929.         *longPtr++ = color;
  930.         *longPtr++ = color;
  931.         *longPtr++ = color;
  932.         *longPtr++ = color;
  933.         *longPtr++ = color;
  934.         *longPtr++ = color;
  935.         *longPtr++ = color;
  936.         *longPtr++ = color;
  937.         *longPtr++ = color;
  938.     }
  939.  
  940. The previous version required 34 cycles per long (12 for the write, 22 for the button
  941. test), or 340 cycles for ten longs. Here, however, the time for ten longs has been cut
  942. down to 142 cycles (120 for the writes, 22 for the button test). Let's go to the big
  943. board and see what our totals are so far: 90x (90x!) faster than the original Button()/
  944. single-byte loop. Jeez, you'd think we could just keep going and eventually fill the
  945. entire screen in just a few cycles, right?
  946.  
  947. Well, no. We've sorta reached the end of the speed-up line. These three tricks are
  948. at the heart of every fast memory operation:
  949.  
  950.   1. find the fastest instruction that moves the most bytes,
  951.   2. keep everything in registers, and 
  952.   3. unroll the loops.
  953.  
  954. Oops. There is a #4.
  955.  
  956.  
  957. #4. Only write to what you need to write to. This goes back to the observation at the
  958. beginning of the message: there're 384 bytes per scan line (in Nick's configuration)
  959. that are unseen (does this remind anyone of the old Apple II text screen holes?). So
  960. why write to them?! Change the loops to for loops: one for 640/4 = 160 longs per scan
  961. line, and one for 480 scan lines. See how fast you can fill the screen. Change the
  962. color on each fill and let it rip. You'll be amazed!
  963.  
  964. Here's my final version of the thing:
  965.  
  966.     register int x, y;
  967.     register long color = 0;
  968.     char mmuMode;
  969.  
  970.     mmuMode = true32b;
  971.     SwapMMUMode( &mmuMode );
  972.  
  973.     while ( *((char *)0x172) < 0 ) {
  974.         register long *rowBase = (long *) baseAddr;
  975.     
  976.         for ( y = 480; y; --y ) {
  977.             register long *longPtr = rowBase;
  978.  
  979.             for ( x = 640/4/10; x; --x ) {
  980.                 *longPtr++ = color;
  981.                 *longPtr++ = color;
  982.                 *longPtr++ = color;
  983.                 *longPtr++ = color;
  984.                 *longPtr++ = color;
  985.                 *longPtr++ = color;
  986.                 *longPtr++ = color;
  987.                 *longPtr++ = color;
  988.                 *longPtr++ = color;
  989.                 *longPtr++ = color;
  990.             }
  991.             rowBase = (long *) ((char *)rowBase + rowBytes);
  992.  
  993.         }
  994.         color += 0x01010101;  // next color
  995.  
  996.     }
  997.  
  998.     SwapMMUMode( &mmuMode );
  999.  
  1000.  
  1001. Have fun!
  1002.  
  1003. /joe
  1004.  
  1005. +++++++++++++++++++++++++++
  1006.  
  1007. From: d88-jwa@musta.nada.kth.se (Jon W{tte)
  1008. Date: 9 Sep 92 12:40:48 GMT
  1009. Organization: Royal Institute of Technology, Stockholm, Sweden
  1010.  
  1011. In article <1992Sep8.191342.15509@adobe.com> jholt@adobe.com (joe holt) writes:
  1012.  
  1013. [ Lots deleted ]
  1014.  
  1015.      1. find the fastest instruction that moves the most bytes,
  1016.      2. keep everything in registers, and 
  1017.      3. unroll the loops.
  1018.  
  1019.    Oops. There is a #4.
  1020.  
  1021.  
  1022.    #4. Only write to what you need to write to. This goes back to the
  1023.  
  1024. That's not only faster, it avoids crashes on some cards.
  1025. You are supposed to NOT write anywhere the screen doesn't
  1026. show your pixels.
  1027.  
  1028. However, your timings are off. If your mac has color, it's
  1029. a 030 mac, where the instructions take much fewer cycles,
  1030. and the relation is different. Not to mention the 68040,
  1031. which uses one or two cycles for manu instructions ! You
  1032. could special-case your code, so if it's on a 040 and the
  1033. moves are cache line aligned, you do a MOVE16 to move four
  1034. longs at a time.
  1035.  
  1036. Note, this is another important thing: alignment. Always
  1037. make sure that reads/writes of size N is integer divisible
  1038. by N (i.e. address modulo N equals 0)
  1039.  
  1040.  
  1041.  
  1042. - -- 
  1043. Jon W{tte, h+@nada.kth.se, Sweden, Phone +46-8-107069
  1044.  
  1045. Help eradicate FIDO-Net <-> Usenet gateways in our time!
  1046.  
  1047. +++++++++++++++++++++++++++
  1048.  
  1049. From: robichau@lambda.msfc.nasa.gov (Paul Robichaux)
  1050. Date: 9 Sep 92 15:31:23 GMT
  1051. Organization: New Technology, Inc.
  1052.  
  1053. In <D88-JWA.92Sep9134048@musta.nada.kth.se> d88-jwa@musta.nada.kth.se (Jon W{tte) writes:
  1054.  
  1055. [ deletia - 4 things to do for fast drawing ]
  1056.  
  1057. >However, your timings are off. If your mac has color, it's
  1058. >a 030 mac
  1059.  
  1060. Nope. The original Mac II and the original Mac LC were both '020 machines.
  1061.  
  1062. - -- 
  1063. Paul Robichaux, KD4JZG          | I shouldn't bitch / I shouldn't cry
  1064. robichau@lambda.msfc.nasa.gov   | I'd start a revolution but I don't have time.
  1065.  
  1066. +++++++++++++++++++++++++++
  1067.  
  1068. From: d88-jwa@cyklop.nada.kth.se (Jon W{tte)
  1069. Organization: Royal Institute of Technology, Stockholm, Sweden
  1070. Date: Wed, 9 Sep 1992 18:28:44 GMT
  1071.  
  1072. > robichau@lambda.msfc.nasa.gov (Paul Robichaux) writes:
  1073.  
  1074.    >However, your timings are off. If your mac has color, it's
  1075.    >a 030 mac
  1076.  
  1077.    Nope. The original Mac II and the original Mac LC were both '020 machines.
  1078.  
  1079. Yeah, right, but!
  1080.  
  1081. I think the timing case should be made for a 030, since that's
  1082. the mainstream processor (and the 040 is fast enough anuyway :-)
  1083.  
  1084. We are already discounting all people running Stepping Out, Radius
  1085. Pivots and SCSI screen boxes, since we don't use the ShieldCursor/
  1086. ShowCursor signalling mechanism.
  1087.  
  1088. - -- 
  1089. Jon W{tte, h+@nada.kth.se, Sweden, Phone +46-8-107069
  1090.  
  1091. Help eradicate FIDO-Net <-> Usenet gateways in our time!
  1092.  
  1093. +++++++++++++++++++++++++++
  1094.  
  1095. From: triantos@acsu.buffalo.edu (Nick B Triantos)
  1096. Date: 10 Sep 92 14:27:51 GMT
  1097. Organization: The University at Buffalo
  1098.  
  1099. Hi, peoples.
  1100.  
  1101. I've been basing some test programs on the code that Joe Holt has provided over
  1102. the past few days (btw, thanks, Joe!).  Anyhow, I'm having a problem as
  1103. follows:  I want to draw blocks of color on my monitor, each of size 40x30, for
  1104. a total of 256, in a 16x16 grid.  Each one will be an increment in color from
  1105. the previous.  I find the base screen address using Joe's method, and then the
  1106. code at the bottom to try to do what I want.
  1107.  
  1108. My two problems are:
  1109. 1.  After my first time cycling through my i for-loop, x_offset is being set
  1110.     to 1, even though x is still 1.
  1111. 2.  More importantly, from the THINK debugger,
  1112.       offset + base_address (an extern Ptr) + i * 1024
  1113.     moves me to the correct scan line, but I get an error compiling with
  1114.     longPtr assigned to this equation because of a type conflict.  But if I
  1115.     type cast base_address to (long *) (as done in the code, see PROBLEM LINE
  1116.     below), it changes the value of longPtr from being incremented 0x0400 to
  1117.     being incremented by 0x1000.  Needless to say, my program therefore
  1118.     doesn't work.  I though I was only moderately rusty with my C.  What am
  1119.     I doing wrong?
  1120.  
  1121. Many thanks,
  1122. - -Nick
  1123.  
  1124. code follows ...
  1125.  
  1126. void DirectDrawTest()
  1127. {
  1128.     register int            x,y ;
  1129.     register long int       x_offset = 0,
  1130.                             y_offset = 0 ;
  1131.     register long int       i ;
  1132.     register long int       color = 0 ;
  1133.     register long int       *longPtr ;
  1134.     register long int       offset ;
  1135.     char                    old_MMUMode ;
  1136.     
  1137.     /* Switch to 32-bit addressing, for 32-bit video cards */
  1138.     if ( (myErr == noErr) && (This_mac.hasColorQD) )
  1139.     {
  1140.         old_MMUMode = true32b ;
  1141.         SwapMMUMode( &old_MMUMode ) ;
  1142.     }
  1143.  
  1144.     /* No need to have the cursor erase my masterpiece... */
  1145.     HideCursor() ;
  1146.  
  1147.     /* Place 16 40x30 squares in each of 16 rows, inc.'ing colors as we go */
  1148.     for ( y = 0 ; y < 16 ; y++ ) /* 16 vert. boxes */
  1149.     {
  1150.         for ( x = 0 ; x < 16 ; x++ ) /* 16 horiz. boxes */
  1151.         {
  1152.             x_offset = 40 * x ; /* 40 horiz. pixels / color box */
  1153.             offset = x_offset + y_offset ;
  1154.             for ( i = 0 ; i < 30 ; i++ ) /* 30 lines of 40 pix. ea per box */
  1155.             {
  1156. PROBLEM LINE:   longPtr = offset + (long *)base_address + i * 1024 ;
  1157.                                                    /* 1024=bytes/scan line */
  1158.                 *longPtr++ = color ;
  1159.                 *longPtr++ = color ;
  1160.                 *longPtr++ = color ;
  1161.                 *longPtr++ = color ;
  1162.                 *longPtr++ = color ;
  1163.                 *longPtr++ = color ;
  1164.                 *longPtr++ = color ;
  1165.                 *longPtr++ = color ;
  1166.                 *longPtr++ = color ;
  1167.                 *longPtr++ = color ;
  1168.             }
  1169.             color += 0x01010101 ;
  1170.         }
  1171.         y_offset += 30 * 1024 ; /* move down 30 pix. after each row of boxes */
  1172.     }
  1173.  
  1174.     /* Go back to old video mode */
  1175.     if ( This_mac.hasColorQD )
  1176.         SwapMMUMode( &old_MMUMode ) ;
  1177.         
  1178.     while (!Button()) ;    /* pause until the mouse button is hit. */
  1179.     
  1180.     ShowCursor() ;
  1181.     
  1182.     if (Button()) while ( Button() ) ;    /* Wait for button release */
  1183. }
  1184. - --
  1185. Nick Triantos    internet: triantos@acsu.buffalo.edu
  1186.                  AOL:      Triantos
  1187. "Scientists tell us that the fastest animal on earth, with a top speed of
  1188. 120 ft/sec, is a cow that has been dropped out of a helicopter." - Dave Barry
  1189.  
  1190. +++++++++++++++++++++++++++
  1191.  
  1192. From: chris@benton.prepress.com (christopher m. knox)
  1193. Date: 10 Sep 92 17:05:49 GMT
  1194. Organization: Pre-Press Technologies, Inc.
  1195.  
  1196. Subject: Re: Game Techniques (was: NON-QUICKDRAW GAMES)
  1197. From: Nick B Triantos, triantos@acsu.buffalo.edu
  1198. In article <BuD6qK.7HM@acsu.buffalo.edu> Nick B Triantos,
  1199. triantos@acsu.buffalo.edu writes:
  1200. >2.  More importantly, from the THINK debugger,
  1201. >      offset + base_address (an extern Ptr) + i * 1024
  1202. >    moves me to the correct scan line, but I get an error compiling with
  1203. >    longPtr assigned to this equation because of a type conflict.  But
  1204. if I
  1205. >    type cast base_address to (long *) (as done in the code, see PROBLEM
  1206. LINE
  1207. >    below), it changes the value of longPtr from being incremented
  1208. 0x0400 to
  1209. >    being incremented by 0x1000.  
  1210. >
  1211. >PROBLEM LINE:   longPtr = offset + (long *)base_address + i * 1024 ;
  1212. >                                                   /* 1024=bytes/scan
  1213. line */
  1214.  
  1215. Greetings...
  1216. I've grappled with the same problem a few times. In C, if you increment a
  1217. pointer, it gets incremented by the size of the base type e.g.:
  1218.     char *pc;
  1219.     long *pl;
  1220.  
  1221. ++pc;    /* gets incremented by 1 byte, since sizeof(char) is 1 byte */
  1222. ++pl;    /* gets incremented by 4 bytes, since sizeof(long) is 4 bytes */
  1223.  
  1224. this is convenient most of the time but also easy to forget. To fix your
  1225. problem line, change it to:  longPtr = (long *) ((long) offset + (long)
  1226. base_address + (long) i * 1024L);
  1227. this performs the calculation as arithmetic rather than pointer
  1228. arithmetic (all the casts
  1229. are not necessary but at least you know exactly what's going on).
  1230. Hope this helps.
  1231. chris knox "Omne animal triste est post (or without) coitum"
  1232.  
  1233. ---------------------------
  1234.  
  1235. End of C.S.M.P. Digest
  1236. **********************
  1237.