home *** CD-ROM | disk | FTP | other *** search
/ Amiga Elysian Archive / AmigaElysianArchive.iso / screen / shdwmstr.lha / source / savers / clock.c < prev    next >
C/C++ Source or Header  |  1991-12-03  |  8KB  |  250 lines

  1. /*
  2.  * A template for use in building new saver graphics.
  3.  *
  4.  * Copyright 1991, Mike Meyer
  5.  * All Rights Reserved
  6.  *
  7.  * See the file "ShadowMaster:Distribution" for information on distribution.
  8.  *
  9.  * ===build instructions
  10.  * % lc clock ; output= clock.o input= clock.c savermain.h
  11.  * % blink clock.o LIB lib:lcr.lib SC SD ; output= clock input=clock.o
  12.  * % copy clock //savers
  13.  * ===endbuild
  14.  *
  15.  * Change the screen title, tags and colorspec to suit you, replace the
  16.  * (trivial) dographics fuction at the bottom with code to do your
  17.  * graphics. It'll be called with the Intuition and Graphics libraries
  18.  * already open, and window and screen open on the stuff you chose.
  19.  * Check SIGBREAKF_CTRL_C at regular intervals, and clean up after
  20.  * yourself and exit when you get it. Return and everything else will be
  21.  * cleaned up and the program will exit.
  22.  *
  23.  * Compile this with large data mode and stack checking off. Use -dNORAND
  24.  * if you don't need the random number generator (rand) intialized.
  25.  */
  26.  
  27. #include <exec/types.h>
  28. #include <intuition/intuition.h>
  29. #include <graphics/gfx.h>
  30. #include <dos/dos.h>
  31. #include <proto/dos.h>
  32. #include <proto/exec.h>
  33. #include <proto/graphics.h>
  34. #include <proto/intuition.h>
  35.  
  36. #ifndef    NORAND        /* So we error out if we did a NORAND but use it */
  37. int rand(void) ;
  38. void srand(int) ;
  39. #endif
  40. static void dographics(void) ;
  41.  
  42. struct ExecBase        *SysBase = NULL ;
  43. struct DosLibrary    *DOSBase = NULL ;
  44. struct IntuitionBase    *IntuitionBase = NULL ;
  45. struct GfxBase        *GfxBase = NULL ;
  46. struct Screen        *screen = NULL ;
  47. struct Window        *window = NULL ;
  48.  
  49. /* Don't change anything above this point... */
  50.  
  51. /*
  52.  * This is the initial color table for the blanker screen. The format of a
  53.  * ColorSpec is pen number, R, G, B. Add pens as required by your screen. You
  54.  * should really set all pens, so you avoid color flashes after opening.
  55.  * If you insist on doing it another way, add SA_ScreenBehind to the screen
  56.  * and do a ScreenToFront after setting the colormap, but before you start
  57.  * drawing.
  58.  *
  59.  * Don't forget to set the SA_Depth tag in ScreenTags...
  60.  */
  61. static struct ColorSpec colorspec[] = {
  62.     {0, 0, 0, 0},
  63.     {1, 8, 8, 8},
  64.     { -1 } } ;
  65.  
  66. /*
  67.  * You must have a better name to use here, right?
  68.  */
  69. static char *Title = "Simple Clock" ;
  70.  
  71. /*
  72.  * Screen open data. You'll probably want to change this to set your own
  73.  * depth and mode. I'd recommend leaving the overscan as is, but it's your
  74.  * graphics hack.
  75.  */
  76. static struct TagItem    ScreenTags[] = {
  77.     {SA_Depth, 1},
  78.     {SA_Colors, &colorspec},
  79.     {SA_DisplayID, HIRESLACE_KEY},
  80.     {SA_Overscan, OSCAN_MAX},
  81.     {SA_Title, &Title},
  82.     {SA_ShowTitle, FALSE},
  83.     {SA_Quiet, TRUE},
  84.     {SA_SysFont, 1},
  85.     {TAG_END, 0}
  86.     } ;
  87.  
  88. /*
  89.  * The window is for turning off the sprite, and that's about it. However,
  90.  * if you want clipped rendering (which means part of your graphics aren't
  91.  * going to be seen), you can use it's rastport. Until you're sure that's
  92.  * not going on, you probably want to do that anyway. After you trust your
  93.  * grahics code, render through the screen rastport to get extra speed.
  94.  *
  95.  * WARNING: WA_CustomScreen _MUST_ be the first entry!!!
  96.  */
  97. static struct TagItem WindowTags[] = {
  98.     {WA_CustomScreen, 0},
  99.     {WA_Borderless, TRUE},
  100.     {WA_Activate, TRUE},
  101.     {WA_SimpleRefresh, TRUE},
  102.     {TAG_END, 0}
  103.     };
  104.  
  105. #include "savermain.h"
  106. /*
  107.  * Add whatever graphics you want here. Be sure and do a
  108.  * CheckSignal(SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C at regular intervals, as
  109.  * that's how you're told to unblank. When that evaluates to true, you should
  110.  * free everything you've allocated and return.
  111.  *
  112.  * Note that we seed the rand() number generator in _main, so that it can
  113.  * happen before we drop the task priority. For saver hacks, that random
  114.  * number generator should be good enough. If you need better, change that
  115.  * seeding. Otherwise, you can just use rand() knowing you'll get different
  116.  * sequences each time you get started. If you really don't want this, just
  117.  * delete the stuff in main.
  118.  *
  119.  * This example doesn't _do_ anything, so it uses a Wait instead of checking
  120.  * signals. We want to be a good citizen.
  121.  */
  122. #include <devices/timer.h>
  123. #include <graphics/gfxbase.h>
  124. #include <graphics/text.h>
  125. #include <dos/rdargs.h>
  126. #include <proto/diskfont.h>
  127.  
  128. /* Resources management isn't trivial here... */
  129. struct MsgPort *Timer_Port = NULL ;
  130. struct timerequest Time_Req = { 0 } ;
  131. struct TextFont *font = NULL ;
  132. struct Library *DiskfontBase = NULL ;
  133. int closefont = FALSE ;
  134.  
  135. int
  136. openresources(void) {
  137.     struct RDArgs *args ;
  138.     long opts[2] = { 0, 0 } ;
  139.     struct TextAttr    *ta, fa ;
  140.     
  141.     /* Set up the timer */
  142.     if ((Timer_Port = CreatePort(NULL, 0)) == NULL
  143.     || OpenDevice(TIMERNAME, UNIT_VBLANK, (struct IORequest *) &Time_Req, 0))
  144.         return FALSE ;
  145.     Time_Req.tr_node.io_Message.mn_ReplyPort = Timer_Port ;
  146.     Time_Req.tr_node.io_Command = TR_ADDREQUEST ;
  147.     Time_Req.tr_node.io_Flags = Time_Req.tr_node.io_Error = 0 ;
  148.  
  149.     /* Get the rest of my resources */
  150.     if ((DiskfontBase = OpenLibrary("diskfont.library", 0)) == NULL
  151.     || (args = ReadArgs("FONT,SIZE/N", opts, NULL)) == NULL)
  152.         return FALSE ;
  153.  
  154.     /* Now get a font */
  155.     if (!opts[0]) {
  156.         ta = screen->Font ;
  157.         font = OpenFont(ta) ;
  158.         }
  159.     else {
  160.         fa.ta_Name = (char *) opts[0] ;
  161.         fa.ta_YSize = opts[1] ? *((long *) opts[1]) : screen->Font->ta_YSize ;
  162.         ta = &fa ;
  163.         font = OpenDiskFont(ta) ;
  164.         }
  165.     if (!(closefont = (int) font)) font = GfxBase->DefaultFont ;
  166.  
  167.     /* Free what I can, and exit */
  168.     FreeArgs(args) ;
  169.     return TRUE ;
  170.     }
  171.  
  172. void
  173. closeresources(void) {
  174.  
  175.     AbortIO((struct IORequest *) &Time_Req . tr_node) ;
  176.     if (closefont) CloseFont(font) ;
  177.     if (DiskfontBase) CloseLibrary(DiskfontBase) ;
  178.     if (Time_Req . tr_node . io_Message . mn_ReplyPort != NULL)
  179.         CloseDevice((struct IORequest *) &Time_Req) ;
  180.     if (Timer_Port != NULL) DeletePort(Timer_Port) ;
  181.     return ;
  182.     }
  183.  
  184.  
  185. void
  186. dographics(void) {
  187.     char Date_Buffer[8] ;    /* Now you know where the time goes! */
  188.     int x_delta = 0, y_delta = 0, x_where, y_where, hours, minutes ;
  189.     struct DateStamp now ;
  190.  
  191.     if (!openresources()) {
  192.         closeresources() ;
  193.         return ;
  194.         }
  195.  
  196.     /* Initialize the world */
  197.     x_where = (rand() >> 16) % (window->Width - 50) ;
  198.     y_where = 25 + ((rand() >> 16) % (window->Height - 25)) ;
  199.     minutes = -1 ;
  200.  
  201.     SetAPen(window->RPort, 1) ;
  202.     SetBPen(window->RPort, 1) ;
  203.     SetDrMd(window->RPort, JAM1) ;
  204.     SetFont(window->RPort, font) ;
  205.     Date_Buffer[3] = ':' ;
  206.     Date_Buffer[0] = Date_Buffer[6] = ' ' ;
  207.     Date_Buffer[7] = '\0' ;
  208.  
  209.     for (;;) {
  210.         DateStamp(&now) ;
  211.         if (minutes != now.ds_Minute % 60) {
  212.             minutes = now.ds_Minute % 60 ;
  213.             hours = now.ds_Minute / 60 ;
  214.             Date_Buffer[1] = hours / 10 + '0' ;
  215.             if (Date_Buffer[1] == '0') Date_Buffer[1] = ' ' ;
  216.             Date_Buffer[2] = hours % 10 + '0' ;
  217.             Date_Buffer[4] = minutes / 10 + '0' ;
  218.             Date_Buffer[5] = minutes % 10 + '0' ;
  219.             do
  220.                 x_delta = (rand() >> 4) % 13 - 6 ;
  221.                 while (x_delta == 0) ;
  222.             do
  223.                 y_delta = (rand() >> 4) % 9 - 4 ;
  224.                 while (y_delta == 0) ;
  225.             }
  226.         SetRast(window->RPort, 0) ;
  227.         Move(window->RPort, x_where, y_where) ;
  228.         Text(window->RPort, Date_Buffer, 7) ;
  229.  
  230.         Time_Req.tr_time.tv_secs = 0 ;
  231.         Time_Req.tr_time.tv_micro = 250000 ;
  232.         SendIO((struct IORequest *) &Time_Req.tr_node) ;
  233.  
  234.         if (Wait(SIGBREAKF_CTRL_C | 1 << Timer_Port->mp_SigBit) & SIGBREAKF_CTRL_C)
  235.             break ;
  236.  
  237.         (void) GetMsg(Timer_Port) ;
  238.  
  239.         /* Now, move the clock */
  240.         if (x_where + x_delta > (window->Width - 50)
  241.          || x_where + x_delta < 0) x_delta = -x_delta ;
  242.         if (y_where + y_delta > (window->Height)
  243.          || y_where + y_delta < 25) y_delta = -y_delta ;
  244.         x_where += x_delta ;
  245.         y_where += y_delta ;
  246.         }
  247.  
  248.     closeresources() ;
  249.     }
  250.