home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1992 #20 / NN_1992_20.iso / spool / comp / sys / mac / programm / 15108 < prev    next >
Encoding:
Text File  |  1992-09-08  |  7.4 KB  |  195 lines

  1. Newsgroups: comp.sys.mac.programmer
  2. Path: sparky!uunet!decwrl!adobe!jholt@adobe.com
  3. From: jholt@adobe.com (joe holt)
  4. Subject: Game Techniques (was: NON-QUICKDRAW GAMES)
  5. Message-ID: <1992Sep8.004821.11323@adobe.com>
  6. Sender: usenet@adobe.com (USENET NEWS)
  7. Organization: Adobe Systems Inc.
  8. Date: Tue, 8 Sep 1992 00:48:21 GMT
  9. Lines: 184
  10.  
  11. Whoa! Slow down. All this talk of palettes is way ahead of schedule. First
  12. we've got to talk about sync'ing to monitor retrace, opening windows and
  13. positioning them on long word boundaries, and--and... Oh, what the heck.
  14.  
  15.  
  16. PALETTES
  17.  
  18. I must be honest and say I didn't know that much about the Palette Manager
  19. until this morning, when I read all of these palette questions and I asked
  20. myself, "Yeah, so how does one do that?" You see, my last serious, for
  21. profit, game endeavor was several years ago when the word on the street was
  22. that the current implementation of the Palette Manager was best avoided.
  23.  
  24. So like any good engineer, I combed the documentation for the lowest-level
  25. access to the video card's clut and used it. This information was available
  26. in the first edition of "Designing Cards and Drivers for the Macintosh
  27. Family (Starring Delta Burke)". Along with the clut calls one could find the
  28. calls for changing a monitor's depth without the pesky Monitors control
  29. panel. Of course this useful information has been removed from subsequent
  30. editions of "Designing Cards" in the interest of public safety (just like
  31. Delta Burke).
  32.  
  33. But now everything works, we've been given SetDepth(), and we should use
  34. what the system provides. And here's what I came up with this morning:
  35.  
  36. The basic strategy is to create a window "around" whatever direct-to-screen
  37. stuff you're going to do, and attach the appropriate palette to it. The
  38. window does two useful things for us: it keeps the rest of the system from
  39. drawing on top of us--that is, it sorta legitimizes our poking onto the
  40. screen (this is what I meant in the first post about screen real estate),
  41. and it gives us an easy place to hang a palette that is used whenever the
  42. window is frontmost.
  43.  
  44. So let's create the window (this code assumes an 8-bit color display and
  45. System 7):
  46.  
  47. // global stuff
  48.  
  49. #include <Palettes.h>
  50.  
  51. static WindowPtr window;
  52. static CTabHandle clut;
  53. static PaletteHandle palette;
  54.  
  55. ..
  56.  
  57. // inside initialization code
  58.  
  59.     Rect bounds;
  60.  
  61.     SetRect( &bounds, 50, 50, 512+50, 384+50 );
  62.     window = NewCWindow( nil, &bounds, "\pRed", true, noGrowDocProc,
  63.         (WindowPtr) -1, true, 0 );
  64.     SetPort( window );
  65.  
  66. And stick a palette onto it:
  67.  
  68.     clut = (CTabHandle) GetResource( 'clut', 128 );
  69.     palette = NewPalette( 32, clut, pmAnimated+pmExplicit, 0 );
  70.     SetPalette( window, palette, false );
  71.  
  72. The 'clut' resource is a ramp from white in index zero to 100% red in
  73. index 31. ResEdit has a blend command which makes this easy. Once you get
  74. this working, experiment with different values in the clut.
  75.  
  76. The flags to NewPalette() tell the Palette Manager that index zero in the
  77. clut resource should be stuck in the video card's clut at index zero, and
  78. so on (pmExplicit), and that no one else can use our colors (pmAnimated).
  79. As I read Inside Mac 6, the combination of these two makes them the highest
  80. priority as the Palette Manager is trying to shoehorn colors into the
  81. hardware clut. Basically we're saying that colors 0 through 31 belong to
  82. us and nobody else, and here they are. Nyah.
  83.  
  84. To see if all of this works, I draw a ramp of my colors into the window
  85. on update events:
  86.  
  87. // In response to update events
  88.  
  89.     int c, y;
  90.     RGBColor black;
  91.  
  92.     y = 0;
  93.     PenSize( 10, 10 );
  94.     black.red = black.green = black.blue = 0;
  95.     TextSize( 9 );
  96.  
  97.     for ( c = 0; c < 32; ++c ) {
  98.         unsigned char text[100];
  99.  
  100.         PmForeColor( c );
  101.         MoveTo( 16, y );
  102.         LineTo( 16384, y );
  103.  
  104.         RGBForeColor( &black );
  105.         MoveTo( 2, y + 9 );
  106.         NumToString( c, text );
  107.         DrawString( text );
  108.  
  109.         y += 12;
  110.     }
  111.     PenNormal();
  112.  
  113. Each line in the window lists an index (0 - 31) and shows a bar of that
  114. color. Using PmForeColor() says we want the RGB color of that particular
  115. index--which, if all this Palette Manager stuff is working, should be the
  116. value that's stored into screen memory. Hmmm... what if I just poked those
  117. values into memory myself?
  118.  
  119. // Do this on mouse downs, or whenever you want
  120.  
  121.     static int c = 0;
  122.     PixMapHandle pix;
  123.     Ptr baseAddr, rowBase, p;
  124.     int rowBytes, x, y;
  125.     char mmuMode;
  126.     Rect bounds;
  127.     unsigned char text[100];
  128.  
  129.     SetRect( &bounds, -32000, -32000, 32000, 32000 );
  130.     pix = (**GetMaxDevice( &bounds )).gdPMap;
  131.     baseAddr = (**pix).baseAddr;
  132.     rowBytes = (**pix).rowBytes & 0x3FFF;
  133.  
  134.     mmuMode = true32b;
  135.     SwapMMUMode( &mmuMode );
  136.     for ( rowBase = baseAddr, y = 30; y; --y ) {
  137.         for ( p = rowBase, x = 30; x; --x ) *p++ = c;
  138.         rowBase += rowBytes;
  139.     }
  140.     SwapMMUMode( &mmuMode );
  141.  
  142.     TextSize( 12 );
  143.     SetRect( &bounds, 485, 0, 16384, 20 );
  144.     EraseRect( &bounds );
  145.     MoveTo( bounds.left + 5, bounds.bottom - 5 );
  146.     NumToString( c, text );
  147.     DrawString( text );
  148.  
  149.     c = (c+1) % 32;
  150.  
  151. I wrote this code as my mouse down handler just to give me an easy way to
  152. trigger it. It draws a rectangle in the upper left corner of the screen by
  153. stuffing values directly into screen memory. The value it stuffs--<c>--is
  154. incremented each time this executes and the value is displayed in the upper
  155. right corner of our window.
  156.  
  157. --> I'm using GetMaxDevice() because my main monitor is a 4-bit grayscale
  158. two-page display, and my second monitor is the 8-bit one where I want the
  159. drawing to take place. Suit to taste.
  160.  
  161. Notice that I SwapMMUMode() around the stuff that actually "draws" into
  162. screen memory. As mentioned before, this is necessary only in certain video
  163. configurations, but for now it doesn't hurt to be safe, and the alternative
  164. is death by poking.
  165.  
  166. So I run this, drag the window over to my 8-bit monitor, and I see a nice
  167. red ramp in the window, white at the top and deep red at the bottom. When I
  168. click the mouse button a white square appears in the corner of my monitor
  169. and the number '0' appears in the window. Each time I click the mouse the
  170. number increments and the square gets redder. Wow.
  171.  
  172. What have I just done? In a system-friendly way, I've forced my will upon
  173. the video hardware and blasted screen memory. I know that a zero written
  174. into screen memory will be color zero from my clut, a one will be color
  175. number one, etc. I know this because I TOLD IT.
  176.  
  177. Just to prove that the Palette Manager is really doing it's job, bring up
  178. the Monitors control panel and play with the screen depth, moving the app
  179. window from frontmost to the back and back and forth. By the way, take a look
  180. at the small clut display at the bottom of the control panel. Is the red
  181. ramp at the start where you think colors 0 - 31 should be? Wrong! The
  182. Monitors control panel shows the entries in reverse order. Go figure.
  183.  
  184. Now of course to really do this right you'd want to put the red square inside
  185. the window. Otherwise the system doesn't know we've been drawing and odd
  186. visuals result. (For example, put the window's drag bar so that it overlaps
  187. the red square and click the mouse button so that the square clobbers part of
  188. the drag bar. Then move the window.) This entails finding the screen address
  189. of the upper left corner of the *window*, and possibly aligning the window on
  190. a long word boundary. But these will have to be subjects of another post, as
  191. this one is already pushing the limits of my concentration.
  192.  
  193. /joe
  194.  
  195.