home *** CD-ROM | disk | FTP | other *** search
/ Amiga Developer CD v1.2 / amidev_cd_12.iso / reference / amiga_mail_vol1 / gfx / disabling_sprite_dma < prev    next >
Text File  |  1990-01-25  |  10KB  |  302 lines

  1. (c)  Copyright 1989 Commodore-Amiga, Inc.   All rights reserved.
  2. The information contained herein is subject to change without notice, and 
  3. is provided "as is" without warranty of any kind, either express or implied.  
  4. The entire risk as to the use of this information is assumed by the user.
  5.  
  6.  
  7. Disabling Sprite DMA From a Vertical Blank Interrupt
  8.  
  9. by Adam Keith Levin
  10.  
  11. An application program such as a screen blanking utility may need
  12. to  disable sprite DMA in order to temporarily turn off sprites. 
  13. The graphics  macro OFF_SPRITE in the graphics library can be
  14. used for this.  However,  if sprite DMA is turned off with
  15. OFF_SPRITE at the exact instant that a  sprite is being rendered,
  16. the sprite image may be "smeared" vertically on  the display. The
  17. SpriteSwitch() program listed below provides a single function
  18. call which uses a vertical blank interrupt to either enable or
  19. disable sprite DMA cleanly, preventing this smearing.
  20.  
  21.  
  22. When You Don't Need SpriteSwitch()
  23.  
  24. If you need to hide the mouse pointer only for your program, not
  25. for the  entire system, you do not need this routine.  Instead
  26. call Intuition's SetPointer() function with the address of a
  27. window belonging to your program, and a definition for a
  28. transparent pointer image.  For example:
  29.  
  30.  SHORT height=1, width=16, x_offset=0, y_offset=0;
  31.  USHORT *pointer_data;
  32.  struct Window *this_window;    /*  A valid window pointer.  */
  33.  
  34.  /*  The smallest possible pointer definition, initialized to
  35.      zeros.  */
  36.  pointer_data =    (USHORT *)AllocMem(12L,MEMF_CHIP|MEMF_CLEAR|MEMF_PUBLIC);
  37.  if (pointer_data)
  38.     SetPointer(this_window, pointer_data, height, width, x_offset,
  39.     y_offset);
  40.  .
  41.  .
  42.  . 
  43.  
  44. if (pointer_data)
  45.     {
  46.         ClearPointer(this_window);
  47.         FreeMem(pointer_data);
  48.     }
  49.  
  50.  
  51. Using this method, the mouse-pointer will disappear whenever
  52. this_window is made active, and reappear when any other window is
  53. made active.  (If you  are opening a window solely for the
  54. purpose of turning off the pointer consider opening a BORDERLESS,
  55. BACKDROP window, which is unobtrusive.)
  56.  
  57.  
  58. When You DO Need SpriteSwitch()
  59.  
  60. Shutting off Sprite DMA will prevent all sprites from being
  61. rendered,  for the entire system.  This is recommended only for
  62. screen-and-mouse  blanker programs or programs that temporarily
  63. take over the system  while running.
  64.  
  65. In general, applications should use SpriteSwitch() as a
  66. substitute for the graphics macro OFF_SPRITE.  The OFF_SPRITE
  67. macro might cause the  sprite image to smear down the screen if
  68. it happens to take effect while  the sprite is being rendered.
  69.  
  70. The SpriteSwitch() function is listed below.  An example call is
  71. also  given in the main routine which is provided here only to
  72. exercise  SpriteSwitch(). To shut off sprite DMA, you call
  73. SpriteSwitch() with the  constant SWITCH_OFF.  To turn on sprite
  74. DMA, call SpriteSwitch() with SWITCH_ON.
  75.  
  76. SpriteSwitch() works by adding a server to the chain of VBLANK
  77. interrupt servers with the AddTOF() system function.  The added
  78. server simply  calls the graphics macro OFF_SPRITE or ON_SPRITE
  79. as appropriate.  Since these  macros are called from within the
  80. VBLANK interrupt, there is no chance that  the sprite is being
  81. rendered at the same time the macro is called, hence,  there is
  82. no way for the sprite to smear.  After the sprite DMA is disabled
  83. (or enabled) SpriteSwitch() calls the system function RemTOF() to
  84. clear the  server from the chain of VBLANK servers.
  85.  
  86.  
  87. Important Note
  88.  
  89. The graphics library's VBLANK server depends upon address
  90. register A0 containing a pointer to the custom chips.  If you add
  91. a server at a priority of ten (10) or greater, you must preserve
  92. the contents of A0 across the call, or otherwise insure that A0
  93. has the correct value. Since this is difficult to do when writing
  94. in C, it is recommended that  VBLANK servers for applications
  95. such as SpriteSwitch() are given a priority of nine (9) or less.
  96.  
  97.  
  98. /*  SpriteSwitch
  99.     Cleanly turns Sprite DMA on or off using a Vertical-Blanking interrupt.
  100.  
  101.     Revision History:
  102.     v1.0    Adam Keith Levin of CATS    Created program.
  103.  
  104.     Lattice (v5.04) make:  LC -b1 -cfist -L -v -y SpriteSwitch.c
  105. */
  106.  
  107. /*  Amiga System includes.  */
  108. #include <exec/types.h>
  109. #include <exec/memory.h>
  110. #include <graphics/gfxmacros.h>
  111. #include <graphics/graphint.h>
  112. #include <hardware/custom.h>
  113. #include <hardware/dmabits.h>
  114. #include <libraries/dos.h>
  115.  
  116. /*  Lattice-specific includes.  */
  117. #ifdef LATTICE
  118. #include <proto/all.h>
  119. #include <stdlib.h>
  120. #endif
  121.  
  122. /*  Amiga.lib prototypes.  */
  123. VOID AddTOF(struct Isrvstr *, APTR, APTR);
  124. VOID RemTOF(struct Isrvstr *);
  125.  
  126. /*  SpriteSwitch request flags.  */
  127. #define SWITCH_ON     0    /*  Turn Sprite DMA on.  */
  128. #define SWITCH_OFF    1    /*  Turn Sprite DMA off.  */
  129.  
  130. /*  Internal indicator that server has completed.  */
  131. #define SWITCH_DONE  ~0    /*  DO NOT USE!  */
  132.  
  133. /*  Error codes.  */
  134. #define ERR_NONE    0    /*  No problems encountered.  */
  135. #define ERR_MEMORY  1    /*  Not enough memory.  */
  136. #define ERR_SIGNAL  2    /*  Unable to allocate a signal bit.  */
  137.  
  138. /*  The Switch_Data structure is used to pass data from the
  139.     spriteSwitch() routine to the spriteSwitchServer() routine.
  140. */
  141. struct Switch_Data
  142. {
  143.     UWORD state;        /*  One of the SpriteSwitch request flags.  */
  144.     struct Task *task;  /*  The task to be signalled.  */
  145.     ULONG signal;       /*  The signal to use.  */
  146. };
  147.  
  148.  
  149. /*  The SpriteSwitch Server.
  150.     Calling "OFF_SPRITE" or "ON_SPRITE" during the Vertical-Blanking Interval
  151.     assures that Sprite DMA will not be shut off while a Sprite is being
  152.     rendered, so their imagery will not get "smeared".
  153. */
  154. int spriteSwitchServer(struct Switch_Data *switch_data)
  155. {
  156. extern struct Custom far custom;    /* Needed by the _SPRITE macros. */
  157.  
  158.     /*  Only run through this once.  */
  159.     if (SWITCH_DONE != switch_data->state)
  160.     {
  161.         switch((int)switch_data->state)
  162.         {
  163.             case (SWITCH_OFF):
  164.                 OFF_SPRITE;
  165.                 break;
  166.             case (SWITCH_ON):
  167.                 ON_SPRITE;
  168.                 break;
  169.             default:
  170.                 break;
  171.         }
  172.  
  173.         /*  Use the state variable to show that the server has already run.  */
  174.         switch_data->state = SWITCH_DONE;
  175.  
  176.         Signal(switch_data->task, switch_data->signal);
  177.     }
  178.  
  179.     return(NULL);
  180. }
  181.  
  182.  
  183. /*  SpriteSwitch.
  184.     Called with a UWORD containing one of the Sprite request flags.
  185.     It initializes a Switch_Data structure with said request flag,
  186.     the task's address (from FindTask(NULL)) and a signal bit (from
  187.     (AllocSignal(-1)).  It installs the SpriteSwitch Server, Wait()s
  188.     for it to signal that the request was completed, and removes it.
  189.     Returns the constant ERR_NONE if successful, ERR_MEMORY if unable
  190.     to allocate enough memory, and ERR_SIGNAL if unable to allocate
  191.     a signal bit.
  192. */
  193. UWORD spriteSwitch(UWORD desired_state)
  194. {
  195. BYTE signal_bit;
  196. UWORD return_value;
  197. /*  The Interrupt Server structure.  When memory is allocated for it,
  198.     all it's fields will be set to NULL, including the priority.
  199.     If a priority other than zero were needed, it could be set
  200.     before the AddTOF() call with:
  201.     isrvstr.is_Node.ln_Pri = (BYTE)my_priority;
  202.     Do not use a priority greater than 9!  (Refer to article for reason).
  203. */
  204. struct Isrvstr *isrvstr = NULL;
  205.  
  206. /*  The Switch_Data structure.  */
  207. struct Switch_Data *switch_data = NULL;
  208.  
  209.     isrvstr = (struct Isrvstr *)
  210.         AllocMem((ULONG)sizeof(struct Isrvstr), MEMF_CLEAR|MEMF_PUBLIC);
  211.     if (NULL != isrvstr)
  212.     {
  213.         switch_data = (struct Switch_Data *)
  214.             AllocMem((ULONG)sizeof(struct Switch_Data), MEMF_PUBLIC);
  215.         if (NULL != switch_data)
  216.         {
  217.             /*  Attempt to allocate a signal bit.  */
  218.             signal_bit = AllocSignal(-1L);
  219.             if (-1 != signal_bit)
  220.             {
  221.                 /*  Initialize the Switch_Data structure.  */
  222.                 switch_data->state = desired_state;
  223.                 switch_data->task = FindTask(NULL);
  224.                 switch_data->signal = (1L << signal_bit);
  225.  
  226.                 /*  Add the server.  */
  227.                 AddTOF(isrvstr, (APTR)spriteSwitchServer, (APTR)switch_data);
  228.  
  229.                 /*  Wait for it to signal that it has completed.  */
  230.                 Wait(1L << signal_bit);
  231.  
  232.                 /*  Remove the server.  */
  233.                 RemTOF(isrvstr);
  234.  
  235.                 /*  Free the signal bit.  */
  236.                 FreeSignal(signal_bit);
  237.  
  238.                 return_value = ERR_NONE;
  239.             }
  240.             else
  241.                 return_value = ERR_SIGNAL;
  242.  
  243.             FreeMem((VOID *)switch_data, (ULONG)sizeof(struct Switch_Data));
  244.         }
  245.         else
  246.             return_value = ERR_MEMORY;
  247.  
  248.         FreeMem((VOID *)isrvstr, (ULONG)sizeof(struct Isrvstr));
  249.     }
  250.     else
  251.         return_value = ERR_MEMORY;
  252.  
  253.     return(return_value);
  254. }
  255.  
  256.  
  257. /*  stdio.h is needed by the main routine.  */
  258. #include <stdio.h>
  259.  
  260. /*  This test routine exercises spriteSwitch() by turning off
  261.     Sprite DMA for five seconds and then turning it back on.
  262. */
  263. VOID main(VOID)
  264. {
  265. UWORD exit_value;
  266.  
  267.  
  268. /*  NOTE:  You may need to OpenLibrary() the graphics library here if your
  269.            compiler complains of an unresolved reference to "GfxBase".
  270.            This is because the module in amiga.lib which contains AddTOF()
  271.            and RemTOF() (which do not require the graphics library) also
  272.            contains calls to routines which do require the graphics library.
  273. */
  274.  
  275.     exit_value = spriteSwitch(SWITCH_OFF);
  276.     if (ERR_NONE == exit_value)
  277.     {
  278.         printf("Sprite DMA shut off.\n");
  279.  
  280.         Delay(5L * TICKS_PER_SECOND);
  281.  
  282.         exit_value = spriteSwitch(SWITCH_ON);
  283.         if (ERR_NONE == exit_value)
  284.             printf("Sprite DMA turned back on.\n");
  285.         else
  286.         {
  287.             printf("Unable to allocate signal bit.\n");
  288.             printf("Sprite DMA not turned back on.\n");
  289.         }
  290.     }
  291.     else
  292.     {
  293.         printf("Unable to allocate signal bit.\n");
  294.         printf("Sprite DMA not shut off.\n");
  295.     }
  296.  
  297.     exit((int)exit_value);
  298. }
  299.  
  300.  
  301.  
  302.