/* * A template for use in building new saver graphics. * * Copyright 1991, Mike Meyer * All Rights Reserved * * See the file "ShadowMaster:Distribution" for information on distribution. * * ===build instructions * % lc clock ; output= clock.o input= clock.c savermain.h * % blink clock.o LIB lib:lcr.lib SC SD ; output= clock input=clock.o * % copy clock //savers * ===endbuild * * Change the screen title, tags and colorspec to suit you, replace the * (trivial) dographics fuction at the bottom with code to do your * graphics. It'll be called with the Intuition and Graphics libraries * already open, and window and screen open on the stuff you chose. * Check SIGBREAKF_CTRL_C at regular intervals, and clean up after * yourself and exit when you get it. Return and everything else will be * cleaned up and the program will exit. * * Compile this with large data mode and stack checking off. Use -dNORAND * if you don't need the random number generator (rand) intialized. */ #include #include #include #include #include #include #include #include #ifndef NORAND /* So we error out if we did a NORAND but use it */ int rand(void) ; void srand(int) ; #endif static void dographics(void) ; struct ExecBase *SysBase = NULL ; struct DosLibrary *DOSBase = NULL ; struct IntuitionBase *IntuitionBase = NULL ; struct GfxBase *GfxBase = NULL ; struct Screen *screen = NULL ; struct Window *window = NULL ; /* Don't change anything above this point... */ /* * This is the initial color table for the blanker screen. The format of a * ColorSpec is pen number, R, G, B. Add pens as required by your screen. You * should really set all pens, so you avoid color flashes after opening. * If you insist on doing it another way, add SA_ScreenBehind to the screen * and do a ScreenToFront after setting the colormap, but before you start * drawing. * * Don't forget to set the SA_Depth tag in ScreenTags... */ static struct ColorSpec colorspec[] = { {0, 0, 0, 0}, {1, 8, 8, 8}, { -1 } } ; /* * You must have a better name to use here, right? */ static char *Title = "Simple Clock" ; /* * Screen open data. You'll probably want to change this to set your own * depth and mode. I'd recommend leaving the overscan as is, but it's your * graphics hack. */ static struct TagItem ScreenTags[] = { {SA_Depth, 1}, {SA_Colors, &colorspec}, {SA_DisplayID, HIRESLACE_KEY}, {SA_Overscan, OSCAN_MAX}, {SA_Title, &Title}, {SA_ShowTitle, FALSE}, {SA_Quiet, TRUE}, {SA_SysFont, 1}, {TAG_END, 0} } ; /* * The window is for turning off the sprite, and that's about it. However, * if you want clipped rendering (which means part of your graphics aren't * going to be seen), you can use it's rastport. Until you're sure that's * not going on, you probably want to do that anyway. After you trust your * grahics code, render through the screen rastport to get extra speed. * * WARNING: WA_CustomScreen _MUST_ be the first entry!!! */ static struct TagItem WindowTags[] = { {WA_CustomScreen, 0}, {WA_Borderless, TRUE}, {WA_Activate, TRUE}, {WA_SimpleRefresh, TRUE}, {TAG_END, 0} }; #include "savermain.h" /* * Add whatever graphics you want here. Be sure and do a * CheckSignal(SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C at regular intervals, as * that's how you're told to unblank. When that evaluates to true, you should * free everything you've allocated and return. * * Note that we seed the rand() number generator in _main, so that it can * happen before we drop the task priority. For saver hacks, that random * number generator should be good enough. If you need better, change that * seeding. Otherwise, you can just use rand() knowing you'll get different * sequences each time you get started. If you really don't want this, just * delete the stuff in main. * * This example doesn't _do_ anything, so it uses a Wait instead of checking * signals. We want to be a good citizen. */ #include #include #include #include #include /* Resources management isn't trivial here... */ struct MsgPort *Timer_Port = NULL ; struct timerequest Time_Req = { 0 } ; struct TextFont *font = NULL ; struct Library *DiskfontBase = NULL ; int closefont = FALSE ; int openresources(void) { struct RDArgs *args ; long opts[2] = { 0, 0 } ; struct TextAttr *ta, fa ; /* Set up the timer */ if ((Timer_Port = CreatePort(NULL, 0)) == NULL || OpenDevice(TIMERNAME, UNIT_VBLANK, (struct IORequest *) &Time_Req, 0)) return FALSE ; Time_Req.tr_node.io_Message.mn_ReplyPort = Timer_Port ; Time_Req.tr_node.io_Command = TR_ADDREQUEST ; Time_Req.tr_node.io_Flags = Time_Req.tr_node.io_Error = 0 ; /* Get the rest of my resources */ if ((DiskfontBase = OpenLibrary("diskfont.library", 0)) == NULL || (args = ReadArgs("FONT,SIZE/N", opts, NULL)) == NULL) return FALSE ; /* Now get a font */ if (!opts[0]) { ta = screen->Font ; font = OpenFont(ta) ; } else { fa.ta_Name = (char *) opts[0] ; fa.ta_YSize = opts[1] ? *((long *) opts[1]) : screen->Font->ta_YSize ; ta = &fa ; font = OpenDiskFont(ta) ; } if (!(closefont = (int) font)) font = GfxBase->DefaultFont ; /* Free what I can, and exit */ FreeArgs(args) ; return TRUE ; } void closeresources(void) { AbortIO((struct IORequest *) &Time_Req . tr_node) ; if (closefont) CloseFont(font) ; if (DiskfontBase) CloseLibrary(DiskfontBase) ; if (Time_Req . tr_node . io_Message . mn_ReplyPort != NULL) CloseDevice((struct IORequest *) &Time_Req) ; if (Timer_Port != NULL) DeletePort(Timer_Port) ; return ; } void dographics(void) { char Date_Buffer[8] ; /* Now you know where the time goes! */ int x_delta = 0, y_delta = 0, x_where, y_where, hours, minutes ; struct DateStamp now ; if (!openresources()) { closeresources() ; return ; } /* Initialize the world */ x_where = (rand() >> 16) % (window->Width - 50) ; y_where = 25 + ((rand() >> 16) % (window->Height - 25)) ; minutes = -1 ; SetAPen(window->RPort, 1) ; SetBPen(window->RPort, 1) ; SetDrMd(window->RPort, JAM1) ; SetFont(window->RPort, font) ; Date_Buffer[3] = ':' ; Date_Buffer[0] = Date_Buffer[6] = ' ' ; Date_Buffer[7] = '\0' ; for (;;) { DateStamp(&now) ; if (minutes != now.ds_Minute % 60) { minutes = now.ds_Minute % 60 ; hours = now.ds_Minute / 60 ; Date_Buffer[1] = hours / 10 + '0' ; if (Date_Buffer[1] == '0') Date_Buffer[1] = ' ' ; Date_Buffer[2] = hours % 10 + '0' ; Date_Buffer[4] = minutes / 10 + '0' ; Date_Buffer[5] = minutes % 10 + '0' ; do x_delta = (rand() >> 4) % 13 - 6 ; while (x_delta == 0) ; do y_delta = (rand() >> 4) % 9 - 4 ; while (y_delta == 0) ; } SetRast(window->RPort, 0) ; Move(window->RPort, x_where, y_where) ; Text(window->RPort, Date_Buffer, 7) ; Time_Req.tr_time.tv_secs = 0 ; Time_Req.tr_time.tv_micro = 250000 ; SendIO((struct IORequest *) &Time_Req.tr_node) ; if (Wait(SIGBREAKF_CTRL_C | 1 << Timer_Port->mp_SigBit) & SIGBREAKF_CTRL_C) break ; (void) GetMsg(Timer_Port) ; /* Now, move the clock */ if (x_where + x_delta > (window->Width - 50) || x_where + x_delta < 0) x_delta = -x_delta ; if (y_where + y_delta > (window->Height) || y_where + y_delta < 25) y_delta = -y_delta ; x_where += x_delta ; y_where += y_delta ; } closeresources() ; }