/******************************************************************************
**********							     **********
**********  			THE ULTIMATE CLOCK                   **********
**********							     **********
*******************************************************************************
**********							     **********
**********       Designed by Magic Ceee, Sanative Secrets 1987       **********
**********							     **********
**********       Based on a novel by Mike Meyers (MCLK). Thanx!      **********
**********							     **********
*******************************************************************************
**********							     **********
**********  This stuff is in the public domain (to add pleasure...)  **********
**********							     **********
******************************************************************************/

#include "libraries/dos.h"
#include "libraries/dosextens.h"
#include "exec/types.h"
#include "exec/memory.h"
#include "exec/io.h"
#include "exec/devices.h"
#include "devices/trackdisk.h"
#include "functions.h"
#include "stdio.h"
#include "exec/tasks.h"
#include "devices/timer.h"
#include "intuition/intuition.h"
#include "intuition/intuitionbase.h"
#include "graphics/gfxbase.h"
#include "libraries/diskfont.h"

#define NO_DISK		"NO DISK"
#define NO_DRIVE	"NO DRIVE"
#define PROTECTED	"-P"
#define NO_SPACE	"FULL"
#define FIRST_STARTUP	"- WAIT -"

#define HELP		"?"
#define NO_COMMERCIAL	"-n"
#define WAKE_ME_UP	"-a"
#define NO_PLEASURE	"\n[33m- No ultimate pleasure for you -[0m\n\n"
#define PLEASURE	"\n[33m- Ultimate pleasure for you!!! -[0m\n\n"
#define BAD_TIME	"\nBad format! Use <[33mTUC -a hh:mm:ss[0m>\n\n"
#define COMMERCIAL	"\nTUC V1.3, by Magic Ceee. Add '?' for help\n"

#define MAGICFLAX	(SMART_REFRESH|WINDOWCLOSE|WINDOWDRAG|WINDOWDEPTH)
#define WAIT_TIME	250000

/*---------------------------------------------------------------------------*/

       struct IntuitionBase	*IntuitionBase;
       struct GfxBase		*GfxBase;
       struct Library		*DiskfontBase;
       struct MsgPort		*diskport;
       struct IOExtTD		*diskreq;
       struct Lock		*lock,*mylock;
       struct Window		*MagicWindow;  
       struct RastPort		*MagicRast;
       struct timerequest	Time_Req;
       struct MsgPort		*Timer_Port;
       struct DateStamp		MagicDate;
       struct IntuiMessage	*MagicMsg;
       struct Task		*FindTask();
extern struct MsgPort 		*CreatePort();
extern struct IORequest 	*CreateExtIO();

struct AlertMessage
       {
        WORD X;
	BYTE Y;
	char text[58];
	BYTE count;
       }
	
texttab[] = {
        80,17,"       Don't panic, son. It's just TUC saying hello...   ",99,
	80,32,"        - This space for rent - This space for rent -    ",0 };

/*---------------------------------------------------------------------------*/

BYTE AlertBuf[20],dfree1[10],dfree2[10],dfree3[10],MagicBuffer[100],
     *led=0xbfe001,*drive[3] = { "DF0:","DF1:","DF2:" };

SHORT dev_error,no_drive=FALSE,disk_status,pleasure=FALSE,prot,alert=FALSE,
      ultimate_fun=FALSE;

/*---------------------------------------------------------------------------*/

struct NewWindow nw = {
	0,0,640,10,1,2,CLOSEWINDOW,MAGICFLAX,NULL,NULL,NULL,NULL,NULL,
	0,0,0,0,WBENCHSCREEN };

struct IntuiText Date_Text = { 1,2,JAM2,0,0,NULL,MagicBuffer,NULL };

struct TextFont *Pleasure8;

struct TextAttr PleasureFont = { "d132.font",8,0,0 };


/*****************************************************************************/

main(argc,argv)
int argc;
char *argv[];
{
 int hours,minutes,secs,i;
 long chip_free,fast_free,total;

 if(!(IntuitionBase=(struct IntuitionBase *)
   OpenLibrary("intuition.library",0)))
     done(20,"Can't open Intuition library");

 if(!(GfxBase=(struct GfxBase *)
   OpenLibrary("graphics.library",0)))
     done(20,"Can't open Graphics library");

 if(!(DiskfontBase=(struct Library *)OpenLibrary("diskfont.library",0)))
     done(20,"Can't open Diskfont library"); 

 i=strcmp(argv[1],NO_COMMERCIAL);
 if(!i) goto mega_schmand;

 i=strcmp(argv[1],WAKE_ME_UP);
 if(!i) 
   {
    alert=TRUE;
    goto mega_schmand;
   } 

 i=strcmp(argv[1],HELP);
 if(!i)
   {
    Tell_The_Truth();
    exit(0);
   }
 
 Print(COMMERCIAL);

mega_schmand:
 if((Timer_Port=CreatePort("Timer Port", 0))==NULL)
   done(20, "Can't create timer port");

 if(OpenDevice(TIMERNAME,UNIT_VBLANK,&Time_Req,0)!= NULL)
   done(20, "Can't open timer device") ;

 Time_Req.tr_node.io_Message.mn_ReplyPort=Timer_Port;
 Time_Req.tr_node.io_Command=TR_ADDREQUEST;
 Time_Req.tr_node.io_Flags=0;
 Time_Req.tr_node.io_Error=0;

 if(!(Pleasure8=(struct TextFont *)OpenDiskFont(&PleasureFont)))
   {
    nw.Width=564;
    nw.LeftEdge=27;
    Print(NO_PLEASURE);
   }

 else
     {
      pleasure=TRUE;
      Print(PLEASURE);
     }
 
 if(!(MagicWindow=OpenWindow(&nw)))
   done(20,"Can't open window");
	
 if(pleasure)
   {
    SetFont(MagicWindow->RPort,Pleasure8);
    strcpy(dfree1,FIRST_STARTUP);
    strcpy(dfree2,FIRST_STARTUP);
    strcpy(dfree3,FIRST_STARTUP);
   }

 SetTaskPri(FindTask(0),20);

 if(alert==TRUE && strlen(argv[2])!=8) Print(BAD_TIME);

 for(;;)
    {
     DateStamp(&MagicDate);
     chip_free=AvailMem(MEMF_CHIP);

     if(chip_free<100000 && ultimate_fun==FALSE)
       {
        DisplayAlert(RECOVERY_ALERT,&texttab,45);
	ultimate_fun=TRUE;
       }

     fast_free=AvailMem(MEMF_FAST);
     total=fast_free+chip_free;
     hours=MagicDate.ds_Minute/60;
     minutes=MagicDate.ds_Minute%60;
     secs=MagicDate.ds_Tick/TICKS_PER_SECOND;

     sprintf(AlertBuf,"%02d:%02d:%02d",hours,minutes,secs);

     if(pleasure)
       {
        if(secs==0 || secs==20 || secs==40) Add_The_Ultimate_Pleasure();

        sprintf(MagicBuffer," Chip: %6ld   Fast: %7ld   Total: %7ld   DF0: %8s   DF1: %8s   DF2: %8s   Time: %02d:%02d:%02d ",
	    chip_free,fast_free,total,dfree1,dfree2,dfree3,hours,minutes,secs);
       }

     else sprintf(MagicBuffer," Chip: %6ld  Fast: %7ld  Total: %7ld  Time: %02d:%02d:%02d",
            chip_free,fast_free,total,hours,minutes,secs);

     PrintIText(MagicWindow->RPort,&Date_Text,28,1);

     if(alert) 
       {
        i=strcmp(AlertBuf,argv[2]);
	if(!i) WakeUp();
       }	

     if(minutes==0 && secs==0)
       {
	for(i=0;i<3;i++)
	   {
            *led|=2;
	    Delay(40);
	    *led&=253;
	    Delay(40);
	   }
       }

     Time_Req.tr_time.tv_secs=0;
     Time_Req.tr_time.tv_micro=WAIT_TIME;
     SendIO(&Time_Req.tr_node);

     Wait(1<<MagicWindow->UserPort->mp_SigBit | 1<<Timer_Port->mp_SigBit);

     while(MagicMsg=GetMsg(MagicWindow->UserPort))
	  {
	   if(MagicMsg->Class==CLOSEWINDOW)
	     {
	      ReplyMsg(MagicMsg);
	      done(0,"exit");
	     }
	   ReplyMsg(MagicMsg);
	  }

     GetMsg(Timer_Port);
    }

}

/*****************************************************************************/

done(how,why)
int how;
char *why;
{
 AbortIO(&Time_Req.tr_node);
 if(MagicWindow) CloseWindow(MagicWindow);
 if(Time_Req.tr_node.io_Message.mn_ReplyPort) CloseDevice(&Time_Req);
 if(Timer_Port) DeletePort(Timer_Port);
 if(IntuitionBase) CloseLibrary(IntuitionBase);
 if(GfxBase) CloseLibrary(GfxBase);
 if(DiskfontBase) CloseLibrary(DiskfontBase);
 exit(how);
}

/*****************************************************************************/

CheckDrive(which_drive,cmd)
int which_drive;
long cmd;
{
 diskport=CreatePort(0,0);

 if(diskport==0) return(0);

 diskreq=(struct IOExtTD *)CreateExtIO(diskport,sizeof(struct IOExtTD));

 if(diskreq==0) 
   {
    DeletePort(diskport); 
    return(0); 
   }
 
 dev_error=OpenDevice(TD_NAME,which_drive,diskreq,0);

 if(dev_error)
   {
    if(which_drive==0) sprintf(dfree1,NO_DRIVE);
    if(which_drive==1) sprintf(dfree2,NO_DRIVE);
    if(which_drive==2) sprintf(dfree3,NO_DRIVE);
    no_drive=TRUE;
    goto knarz;
   }

 diskreq->iotd_Req.io_Command=cmd;
 DoIO(diskreq);
 disk_status=diskreq->iotd_Req.io_Actual;

 if(disk_status==255)
   {
    if(which_drive==0) sprintf(dfree1,NO_DISK);
    if(which_drive==1) sprintf(dfree2,NO_DISK);
    if(which_drive==2) sprintf(dfree3,NO_DISK);
    no_drive=TRUE;
   }

 CloseDevice(diskreq);
knarz:
 DeleteExtIO(diskreq, sizeof(struct IOExtTD));
 DeletePort(diskport);
}
 
/*****************************************************************************/

struct IORequest *CreateExtIO(ioReplyPort,size)
struct MsgPort *ioReplyPort;
LONG size;
{
 struct IORequest *ioReq;
 
 if(ioReplyPort==0) return((struct IORequest *)0);
 
 ioReq=(struct IORequest *)AllocMem(size,MEMF_CLEAR|MEMF_PUBLIC);
 
 if(ioReq==0) return((struct IORequest *)0);
 
 ioReq->io_Message.mn_Node.ln_Type=NT_MESSAGE;
 ioReq->io_Message.mn_Node.ln_Pri=0;
 ioReq->io_Message.mn_ReplyPort=ioReplyPort;
 
 return(ioReq);
}
  
/*****************************************************************************/

DeleteExtIO(ioExt,size)
struct IORequest *ioExt;
LONG size;
{
 ioExt->io_Message.mn_Node.ln_Type=0xff;
 ioExt->io_Device=(struct Device *)-1;
 ioExt->io_Unit=(struct Unit *)-1;
 
 FreeMem (ioExt, size);
}

/*****************************************************************************/

GetDFree(which)
int which;
{
 long free;

 if(lock=Lock(drive[which],ACCESS_READ))
       {
        free=avail(lock);
        UnLock(lock);
       }   

 if(which==0 && free!=0) sprintf(dfree1,"%6ld",free);
 else if(which==0 && free==0) sprintf(dfree1,"%s",NO_SPACE);

 if(which==1 && free!=0) sprintf(dfree2,"%6ld",free);
 else if(which==1 && free==0) sprintf(dfree2,"%s",NO_SPACE);

 if(which==2 && free!=0) sprintf(dfree3,"%6ld",free);
 else if(which==2 && free==0) sprintf(dfree3,"%s",NO_SPACE);

 if(prot)
   {
    if(which==0) strcat(dfree1,PROTECTED);
    if(which==1) strcat(dfree2,PROTECTED);
    if(which==2) strcat(dfree3,PROTECTED);
   } 
}

/*---------------------------------------------------------------------------*/

avail(disk)
struct Lock **disk;
{
 struct InfoData *info;

 long bytes;

 info=AllocMem(sizeof(struct InfoData),MEMF_PUBLIC);
 Info(disk,info);
 bytes=(info->id_NumBlocks-info->id_NumBlocksUsed)*info->id_BytesPerBlock;
 FreeMem(info,sizeof(struct InfoData));
 return(bytes);
}

/*****************************************************************************/

Add_The_Ultimate_Pleasure()
{
 int i;

 for(i=0;i<3;i++)
    {
     CheckDrive(i,TD_CHANGESTATE);

     if(no_drive==FALSE)
       {
	CheckProt(i);
        GetDFree(i);
       }

     else no_drive=FALSE;
    }	
}

/*****************************************************************************/

Tell_The_Truth()
{
 int i,j;

 MagicRast=IntuitionBase->FirstScreen->FirstWindow->RPort;

 Print("\n\n\n");
 Print("[33m       THE ULTIMATE CLOCK - MADE FOR YOU TO ADD THE ULTIMATE PLEASURE[0m\n");
 Print("               - Designed by Magic Ceee, 18-Dec-87, 08:31:49 -\n\n");
 Print("      To add ultimate pleasure,there has to be a 132-colums font named\n");
 Print("      <[1md132.font[0m>  in the  directory  currently  assigned to \"fonts:\".\n");
 Print("      This beastie then will provide the ultimate memory report, which\n");
 Print("      will be updated  every 20 seconds. If you don't have such a font\n");
 Print("      handy, you'll face the  simple memory clock, which has  actually\n");
 Print("      a lack of pleasure.\n");
 Print("      To kick the \"[1mAdd '?' for help[0m\" - prompt, add \"[1m-n[0m\" to the command\n");
 Print("      line. To enable the alert funktion, type [33mTUC -a hh:mm:ss[0m to  get\n");
 Print("      alarmed when your time has come. Have fun!\n\n");
 Print("               - Designed by Magic Ceee, 18-Dec-87, 08:31:49 -\n");
 Print("[33m       THE ULTIMATE CLOCK - MADE FOR YOU TO ADD THE ULTIMATE PLEASURE[0m\n");

 for(j=0;j<3;j++)
    {
     for(i=0;i<10;i++)
	 ScrollRaster(MagicRast,0,-1,2,10,600,180);

     for(i=0;i<10;i++)
         ScrollRaster(MagicRast,0,1,2,10,600,180);
    }

 bye:
  CloseLibrary(IntuitionBase);
  CloseLibrary(GfxBase);
}

/*****************************************************************************/

WakeUp()
{
 int i;

 for(i=0;i<5;i++)
    {
     DisplayBeep(IntuitionBase->FirstScreen);
     *led|=2;
     Delay(40);
     *led&=253;
     Delay(40);
    }
} 

/*****************************************************************************/

CheckProt(which_drive)
int which_drive;
{
 struct InfoData	*id;
 struct lock		*templock;
 int success;

 prot=FALSE;
 id=(struct InfoData *)AllocMem(sizeof(struct InfoData),MEMF_CLEAR);
 templock=Lock(drive[which_drive],ACCESS_READ);

 if(templock)
   {
    success=Info(templock,id);
   
    if(success)
      if(id->id_DiskState==ID_WRITE_PROTECTED) prot=TRUE;
    UnLock(templock);
   }

 FreeMem(id,sizeof(struct InfoData));
}
   
/*****************************************************************************/

Print(s)
char *s;
{
 Write(Output(),s,strlen(s));
}
