home *** CD-ROM | disk | FTP | other *** search
/ The Utilities Experience / The Utilities Experience - Volume 1.iso / software / graphics / a-g / beyondthedark / developer / source / skeleton / skeleton.c < prev   
Encoding:
C/C++ Source or Header  |  1995-12-21  |  11.2 KB  |  413 lines

  1. /* 
  2.    Skeleton Library for BTD 
  3.    Comments by Markus Illenseer 
  4.   
  5.    This source tries to give valuable hints to write a Modul
  6.    for BTD. As you will see, this is quite easy, even if it is
  7.    the first time you write a library.
  8.  
  9.    This Skeleton Blanker draws random dots in 4 colors for a certain time,
  10.    then cleans up the screen and starts again. Nothing sophisticated.
  11.  
  12.    Also do refer to BTD.h for global defines and structures.
  13.  
  14. */
  15.  
  16. #include <exec/memory.h>
  17. #include <exec/execbase.h>
  18. #include <libraries/iffparse.h>
  19. #include <utility/tagitem.h>
  20.  
  21. #include <clib/macros.h>
  22.  
  23. #define __USE_SYSBASE 42
  24.  
  25. #include <proto/exec.h>
  26. #include <proto/graphics.h>
  27. #include <proto/intuition.h>
  28.  
  29. #include <BTD.h>
  30.  
  31. struct ExecBase *SysBase;
  32. struct IntuitionBase *IntuitionBase;
  33. struct GfxBase *GfxBase;
  34.  
  35. /* 
  36.    Don't open any libraries by yourself. This _must_ be done
  37.    in the assembler part of the library. 
  38.  
  39.    Be sure your library is re-entrant. Means, one must be able to
  40.    open the library several times at once. So don't use global 
  41.    variables other than static (unchangable) ones. Use ModulStruct
  42.    for that purpose.
  43. */
  44.  
  45. /* #define DEBUG YES */
  46.  
  47. /*
  48.    Remove above comment braces (uncomment) to use the Debug-Output.
  49.    Use Terminal connected to serial line, or use sushi to
  50.    redirect the output. Be carefull with modems!
  51.    Remember to add the Debug.lib in the Makefile.
  52.  
  53.    DEBUG_PRINT prints only text.
  54.    DEBUG_PRINTF prints any text and one (!) variable of any kind
  55.  
  56.    This is the only easy way to debug libaries! The SDB or other
  57.    debuggers have some problems with libraires, at least as source
  58.    level debuggers.
  59.  
  60. */
  61.  
  62. #ifdef DEBUG 
  63.  
  64. void KPrintF(char *,...);
  65.  
  66. #define DEBUG_PRINTF(a,b)  KPrintF(a,b);
  67. #define DEBUG_PRINT(a)     KPrintF(a)
  68. #else
  69. #define DEBUG_PRINTF(a,b)
  70. #define DEBUG_PRINT(a)
  71. #endif
  72.  
  73. /* Now we define the Macros for easy access to the Tag-Entries */
  74.  
  75. #define DTAG(o) (BTD_Client+(o))
  76.  
  77. #define ST_Seconds DTAG(0)
  78.  
  79. /* How much time we give, until the screen is cleaned up again */
  80.  
  81. #define DEF_SECONDS 5L
  82. #define MAX_SECONDS 60L
  83.  
  84. /*
  85.    This structure defines the INTEGER parameters, which the user
  86.    can supply.  Skeleton requires only the seconds until it will
  87.    clean up the screen.  For other type of paramters, refer to BTD.h 
  88. */
  89.  
  90. struct BTDInteger SkeletonIntParams[] =
  91.  {
  92.   ST_Seconds,"Seconds",BTDPT_INTEGER,DEF_SECONDS,1L,MAX_SECONDS,TRUE,
  93.  };
  94.  
  95. /*
  96.    This Taglist is send to the Preference-Programm which will
  97.    open a window with the hereby supplied gadgets.  Skeleton needs
  98.    only the one Integer-Slider 
  99. */
  100.  
  101. struct BTDNode *SkeletonParams[] = 
  102.  {
  103.   &SkeletonIntParams[0].BI_Node,
  104.   NULL
  105.  };
  106.  
  107. /*
  108.    This structure sends some info about the modul to the Preference-
  109.    Programm.  MAKE_ID is required for MUI, and will make it possible
  110.    to save the position of this specific preference window.
  111.    First string defines the NAME of the blanker, possibly something
  112.    different than the probaly cryptic filename of the library.
  113.    Second string contains a short description about the blanker.  A \n will
  114.    split up the string into a new line.
  115.    Third string should contain your Name and a Copyright message if
  116.    necessary.
  117.  
  118.    The Version Number is not defined here, but in the Assembler-Part
  119.    of the source!
  120.  
  121.    Last Tag is the Node-Info, which will request the user for parameters
  122.    with above given List in BTDNode.
  123. */
  124.  
  125. struct BTDInfo SkeletonInfo =
  126.  {
  127.   BTDI_Revision,MAKE_ID('S','K','E','L'),
  128.   "Skeleton Blanker","Skeleton is intended for programmers\n among you peoples!\nJust a simple and boring blanker modul","Markus Illenseer 1994",
  129.   SkeletonParams
  130.  };
  131.  
  132.  
  133. /*
  134.    This is our 'global' structure for the skeleton blanker. I refer to
  135.    it as ModulStruct.
  136.    Remember that this is the only way to hold global data for each 
  137.    invoked modul out of this library. The Skeleton Blanker will only 
  138.    hold info about the supplied second-parameter and about the time when 
  139.    the screen was cleaned up the last time. And of course it will hold 
  140.    the BTDDrawInfo, which contains lot of required info, eg. RastPort.
  141.  
  142.    If you require anything sophisticated like ImageData, have a look into
  143.    the other supplied modules. 
  144. */
  145.  
  146. struct SkeletonStruct
  147.  {
  148.   struct BTDDrawInfo *BTDDrawInfo;
  149.   LONG Seconds;
  150.   LONG Time;
  151.   LONG RandN,RandF,RandI;
  152.  };
  153.  
  154. /*
  155.    The next two functions are some sophisticated Randomnizers
  156.    which are based upon (mathematic) statistic defined true 
  157.    Randomnizers. All they need is a seed, afterwards they will use
  158.    the current time as a base for future randoms. 
  159.  
  160.    Normally we would have some global variabled for RandN, RandF and
  161.    RandI, but as we need to be re-entrant, we need to store this info
  162.    in the ModulStruct above. 
  163. */
  164.  
  165. void __regargs InitRandom(struct SkeletonStruct *Skel,ULONG Instance)
  166.  
  167. {
  168.  ULONG Time[2];
  169.  
  170.  CurrentTime (&Time[0],&Time[1]);
  171.  Skel->RandN=(LONG)Time[0];
  172.  
  173.  if (Time[1]<1024L) Time[1]|=1;
  174.  else Time[1]>>=10;
  175.  Time[1]^=Instance;
  176.  
  177.  Skel->RandF=4*Time[1]+1;
  178.  Skel->RandI=2*Time[1]+1;
  179. }
  180.  
  181. WORD __regargs Random(struct SkeletonStruct *Skel,WORD Max)
  182.  
  183. {
  184.  Skel->RandN=Skel->RandF*Skel->RandN+Skel->RandI;
  185.  if (Skel->RandN<0L) Skel->RandN=-Skel->RandN;
  186.  
  187.  return (WORD)(Skel->RandN%Max);
  188. }
  189.  
  190.  
  191. /* 
  192.    This function is actually a copy of the FindTag-function of clib/utility,
  193.    but this one is a bit faster and also returns a supplied Default
  194.    when Tag-ID wasn't found 
  195. */
  196.  
  197. ULONG FindTagData(struct TagItem *TagList,Tag ID,ULONG Default)
  198.  
  199. {
  200.  while (TagList)
  201.   switch (TagList->ti_Tag)
  202.    {
  203.     case TAG_DONE:
  204.      return Default;
  205.     case TAG_MORE:
  206.      TagList=(struct TagItem *)TagList->ti_Data;
  207.      break;
  208.     default:
  209.      if (TagList->ti_Tag==ID) return TagList->ti_Data;
  210.      else TagList++;
  211.    }
  212.  return Default;
  213. }
  214.  
  215. /* 
  216.    This is the first procedure every modul requires. It will initialize
  217.    the modul, eat required memory, set colors, whatever. This function
  218.    should be as short as possible. No heavy calculations belong here 
  219.  
  220.    struct ModulStruct InitModul(struct TagItem *TagList)
  221.  
  222.    Input: TagList is supplied from BTD-CX, the server, and will send
  223.           you all the parameters you requested from the user in above
  224.           structure BTDInfo. 
  225.  
  226.    Output: Fully initialized ModulStruct for further use, is returned
  227.            to the server, who will then invoke AnimModul() with this
  228.            structure. 
  229. */
  230.  
  231. struct SkeletonStruct *InitSkeleton(struct TagItem *TagList)
  232.  
  233. {
  234.  struct SkeletonStruct *SkelStruct;
  235.  struct BTDDrawInfo *BTDDrawInfo;
  236.  ULONG *Error,Dummy,Instance,Index;
  237.  
  238. DEBUG_PRINT("Skeleton: Initialize Modul\n");
  239.  
  240.  /* Find the Entry for the BTDDrawInfo (see BTD.h) and make local copy */
  241.  
  242.  if ((BTDDrawInfo=(struct BTDDrawInfo *)
  243.                    FindTagData(TagList,BTD_DrawInfo,NULL))==NULL) return NULL;
  244.  
  245. /* 
  246.    Get us the Dummy, which will contain Error-Messages if we fail to
  247.    initialize our Modul. The server then knows we failed and will display
  248.    a black part on the screen 
  249. */
  250.  
  251.  Error=(LONG *)FindTagData(TagList,BTD_Error,(ULONG)&Dummy);
  252.  
  253. /*
  254.    Allocate the required MEM for the SkeletonStruct, on error report
  255.    a Memory-error to the server and return home 
  256. */
  257.  
  258.  if ((SkelStruct=AllocVec(sizeof(struct SkeletonStruct),MEMF_PUBLIC|MEMF_CLEAR))==NULL)
  259.   {
  260.    *Error=BTDERR_Memory;
  261.    return NULL;
  262.   }
  263.  
  264. /*
  265.    copy local BTDDrawInfo into global structure for future use in 
  266.    AnimModul() 
  267. */
  268.  
  269.  SkelStruct->BTDDrawInfo=BTDDrawInfo;
  270.  
  271. /*
  272.   The Instance is sort of OpenCounter and is often used to initialize
  273.   a Randomnizer, so that same modules won't use same random-seed 
  274. */
  275.  
  276.  Instance=FindTagData(TagList,BTD_Instance,0L);
  277.  
  278.  InitRandom(SkelStruct,Instance);
  279.  
  280. /* Get us the user-supplied parameter SECONDS */
  281.  
  282.  SkelStruct->Seconds=FindTagData(TagList,ST_Seconds,DEF_SECONDS);
  283.  
  284.  
  285. /* 
  286.   Set an initial value, not really required to do so, as we allocated
  287.   the SkelStruct with MEMF_CLEAR flag 
  288. */
  289.  
  290.  SkelStruct->Time=0L;
  291.  
  292.  
  293. /* 
  294.   Now set our requested colors to any RGB-Tripel, you MUST use
  295.   this array, otherwise you won't get your colors, but anything
  296.   else. Can yield to a Guru if you do that! 
  297. */
  298.  
  299.  for(Index=0; Index<4; Index++)
  300.   {
  301.    BTDDrawInfo->BDI_Red[BTDDrawInfo->BDI_Pens[Index]]=Random(SkelStruct,255);
  302.    BTDDrawInfo->BDI_Green[BTDDrawInfo->BDI_Pens[Index]]=Random(SkelStruct,255);
  303.    BTDDrawInfo->BDI_Blue[BTDDrawInfo->BDI_Pens[Index]]=Random(SkelStruct,255);
  304.    BTDDrawInfo->BDI_Changed[BTDDrawInfo->BDI_Pens[Index]]=TRUE;
  305.   }
  306.  
  307. /* Everything's done. Return the structure for future use */
  308.  
  309.  return SkelStruct;
  310. }
  311.  
  312. /* This is the second procedure required for every modul. It should
  313.    do anything required to free resources, free mem and so on. 
  314.  
  315.    void EndSkeleton(struct ModulStruct *ModulStruct)
  316.  
  317.    Input: ModulStruct supplied from server BTD-CX
  318.    Output: None. Should all be freed up */
  319.  
  320. void EndSkeleton(struct SkeletonStruct *SkelStruct)
  321.  
  322. {
  323. DEBUG_PRINT("Skeleton: about to finish Modul\n");
  324.  FreeVec (SkelStruct);
  325. }
  326.  
  327. /* Third procedure required for a modul. This one is called by the
  328.    server every once in a second. You are not allowed to do anything
  329.    which would yield into a FOREVER-Loop or do anything like a busy-loop
  330.    or something unstoppable. 
  331.  
  332.    If you need to do a loop from TOP to BOTTOM (TOP+HEIGHT), add a counter
  333.    in ModulStruct: ypos. Best would even to add xpos also, if required.
  334.    
  335.    These restictions are all due to the fact, that the user want's his
  336.    screen back as fast as possible!
  337.  
  338.    void AnimSkeleton(struct ModulStruct *ModulStruct)
  339.  
  340.    Input: ModulStruct supplied from server BTD-CX.
  341.    OutPut: None.
  342.  
  343. */
  344.  
  345. void AnimSkeleton(struct SkeletonStruct *SkelStruct)
  346.  
  347. {
  348.  ULONG Seconds,Micros;
  349.  
  350.  /* Hum, below DEBUG_PRINT not that usefull. Remove it, or replace
  351.     it with anything you need to check */
  352.  
  353. DEBUG_PRINT("Skeleton: Animate\n");
  354.  
  355. /* Get us the current time. */
  356.  
  357.  CurrentTime (&Seconds,&Micros);
  358.  
  359.  if (Seconds>=SkelStruct->Time)
  360.   {
  361.  
  362. /* Wait for that the pointer is at the top of the screen */
  363.    WaitTOF();
  364.  
  365. /* Calculate next timeslide */
  366.  
  367.    SkelStruct->Time=Seconds+SkelStruct->Seconds;
  368.    
  369. /* Set Background color, attention, have a look at the color! */
  370.  
  371.    SetAPen(SkelStruct->BTDDrawInfo->BDI_RPort,BTD_BgPen);
  372.  
  373. /* Fill our part of the screen with background color */
  374.  
  375.    RectFill (SkelStruct->BTDDrawInfo->BDI_RPort,
  376.              SkelStruct->BTDDrawInfo->BDI_Left,
  377.              SkelStruct->BTDDrawInfo->BDI_Top,
  378.              SkelStruct->BTDDrawInfo->BDI_Left+SkelStruct->BTDDrawInfo->BDI_Width-1,
  379.              SkelStruct->BTDDrawInfo->BDI_Top+SkelStruct->BTDDrawInfo->BDI_Height-1);
  380.   }
  381.  
  382. /* Now let's do the magic Animation of Skeleton */
  383.  
  384. /* Choose Random Color and set Pen accordingly */
  385.  
  386.   SetAPen (SkelStruct->BTDDrawInfo->BDI_RPort,
  387.            SkelStruct->BTDDrawInfo->BDI_Pens[Random(SkelStruct,4)]);
  388.  
  389. /* 
  390.   You can speed up the process, if you store LEFT, TOP, HEIGHT. WIDTH
  391.   in ModulStruct directly, rather than in a pointer to BTDDrawInfo 
  392. */
  393.  
  394.   WritePixel (SkelStruct->BTDDrawInfo->BDI_RPort,
  395.               SkelStruct->BTDDrawInfo->BDI_Left+Random(SkelStruct,SkelStruct->BTDDrawInfo->BDI_Width),
  396.               SkelStruct->BTDDrawInfo->BDI_Top+Random(SkelStruct,SkelStruct->BTDDrawInfo->BDI_Height));
  397. }
  398.  
  399. ULONG PenCountSkeleton(struct TagItem *TagList)
  400.  
  401. {
  402.  
  403. /*
  404.    We request to use 4 colors, we _will_ get them! 
  405.    We would even get 324 colors, if there is a screenmode with that
  406.    many colors, and the servers gives us that many. 
  407.    If the servers sees that we need more colors as he can provide with
  408.    his used screenmode, he won't use our modul 
  409. */
  410.  
  411.  return 4L;
  412. }
  413.