home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 423.lha / Talker_II / TalkerII.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-10-05  |  27.3 KB  |  871 lines

  1.  
  2.                      /*--------------------------*|
  3.                      |     TalkerII.c   10/01/90  |
  4.                      |*--------------------------*/
  5.  /*=====================================================================*/
  6.  /*    Talker II Display Hack   --                                      */
  7.  /*    VERSION 1                                         REVISION 0     */
  8.  /*---------------------------------------------------------------------*/
  9.  /*   This is the primary file for Talker II.                           */
  10.  /* It encompasses all major routines, including those dealing with     */
  11.  /* Message retrieval.                                                  */
  12.  /*---------------------------------------------------------------------*/
  13.  /*   Talker II is based around the example routines for using the      */
  14.  /* narrator/translator devices from "Inside The Amiga". Because of     */
  15.  /* this, even though I made changes to the original code (to make it   */
  16.  /* work), I don't feel I can retain a copyright on it. Special thanks  */
  17.  /* to Keith Young (Access!) for his help with dealing with command     */
  18.  /* line arguments, along with much other assistance.                   */
  19.  /*=====================================================================*/
  20.  
  21.  /*        Auto: cc -su TalkerII.c
  22.  
  23.  */
  24.  
  25. #define ERR 1L
  26. #define SUCCESS 0L
  27. #define REV 0L
  28.  
  29. #include "exec/types.h"
  30. #include "exec/exec.h"
  31. #include "intuition/intuition.h"
  32. #include "intuition/intuitionbase.h"
  33. #include "devices/keymap.h"
  34. #include "hardware/blit.h"
  35. #include "devices/narrator.h"
  36. #include "libraries/translator.h"
  37. #include "graphics/view.h"
  38. #include "stdio.h"
  39. #include "stdlib.h"
  40. #include "clib/macros.h"
  41. #include "faceII.h"
  42. #include "eyesII.h"
  43. #include "mouthyII.h"
  44. #include "mouthxII.h"
  45. #include "browsII.h"
  46. #include "stdio.h"
  47.  
  48. ULONG mclass;
  49. struct Image *newmouth,*neweyes;
  50. char in_string[256], out_string[1024];
  51.  
  52.          /* select which audio channels to use */
  53.  
  54. UBYTE audio_chan[] = {
  55.                       3,5,10,12
  56.                      };
  57.  
  58.        struct Library *OpenLibrary();
  59.        struct Library *TranslatorBase = NULL;
  60.        struct MsgPort *voice_port; /* audio message port */
  61.        struct MsgPort *mouth_port; /* video message port */
  62.        struct mouth_rb *mouth_io;
  63.        struct narrator_rb *voice_io;
  64.        struct IntuitionBase *IntuitionBase = NULL;
  65.        struct GfxBase   *GfxBase   = NULL;
  66.        struct Screen *TalkerScreen = NULL;
  67.        struct Window *TalkerWindow = NULL;
  68.        struct ViewPort *Vprt       = NULL;
  69.        struct RastPort *rast       = NULL;
  70.        struct IntuiMessage *mesg   = NULL;
  71.  
  72.  
  73.           /*====================================================*/
  74.           /*  LookArray[][] is for determining which eye image  */
  75.           /*  to show. The first 6 elements look left, the 2nd  */
  76.           /*  6 elements look right.                            */
  77.           /*====================================================*/
  78.  
  79. struct Image *LookArray[2][6] = {
  80.                                  &eyes0_Image,&eyes3_Image,&eyes4_Image,
  81.                                  &eyes4_Image,&eyes3_Image,&eyes0_Image,
  82.                                  &eyes0_Image,&eyes5_Image,&eyes6_Image,
  83.                                  &eyes6_Image,&eyes5_Image,&eyes0_Image
  84.                                 };
  85.  
  86.             /*=================================================*/
  87.             /*  EyeArray[] is for determining which eye image  */
  88.             /*  to show as the Talker blinks. Note that the    */
  89.             /*  sequence is open, mid, closed, open. There is  */
  90.             /*  NOT an element for mid as the eye reopens.     */
  91.             /*  This appears more realistic, to me.            */
  92.             /*=================================================*/
  93.  
  94. struct Image *EyeArray[4] = {
  95.                              &eyes0_Image,
  96.                              &eyes1_Image,
  97.                              &eyes2_Image,
  98.                              &eyes0_Image
  99.                             };
  100.  
  101.              /*===============================================*/
  102.              /*  HArray[] is used to determine which mouth    */
  103.              /*  image to show. It is used for the sequences  */
  104.              /*  where the height value is greater than the   */
  105.              /*  width value.                                 */
  106.              /*===============================================*/
  107.  
  108. struct Image *HArray[16] = {
  109.                             &mouthx0_Image, &mouthx0_Image,
  110.                             &mouthx1_Image, &mouthx3_Image,
  111.                             &mouthx3_Image, &mouthx4_Image,
  112.                             &mouthx5_Image, &mouthx6_Image,
  113.                             &mouthx7_Image, &mouthx7_Image,
  114.                             &mouthx8_Image, &mouthx9_Image,
  115.                             &mouthx10_Image, &mouthy11_Image,
  116.                             &mouthy11_Image, &mouthy12_Image 
  117.                            };
  118.  
  119.  
  120.              /*===============================================*/
  121.              /*  WArray[] is used to determine which mouth    */
  122.              /*  image to show. It is used for the sequences  */
  123.              /*  where the width value is greater than the    */
  124.              /*  height value.                                */
  125.              /*===============================================*/
  126.  
  127. struct Image *WArray[16] = {
  128.                             &mouthy0_Image, &mouthy0_Image,
  129.                             &mouthy1_Image, &mouthy2_Image,
  130.                             &mouthy3_Image, &mouthy3_Image,
  131.                             &mouthy4_Image, &mouthy5_Image,
  132.                             &mouthy6_Image, &mouthy7_Image,
  133.                             &mouthy7_Image, &mouthy8_Image,
  134.                             &mouthy9_Image, &mouthy10_Image,
  135.                             &mouthy11_Image, &mouthy12_Image 
  136.                            };
  137.  
  138.              /*===============================================*/
  139.              /*  BArray[] is used to determine which mouth    */
  140.              /*  image to show. It is used for the sequences  */
  141.              /*  where the height value is equal to the       */
  142.              /*  width value.                                 */
  143.              /*===============================================*/
  144.  
  145. struct Image *BArray[16] = {
  146.                             &mouthx0_Image, &mouthx1_Image,
  147.                             &mouthx2_Image, &mouthy3_Image,
  148.                             &mouthy4_Image, &mouthy5_Image,
  149.                             &mouthy6_Image, &mouthy7_Image,
  150.                             &mouthy8_Image, &mouthy8_Image,
  151.                             &mouthy9_Image, &mouthy9_Image,
  152.                             &mouthy10_Image, &mouthy11_Image,
  153.                             &mouthy12_Image, &mouthy12_Image 
  154.                            };
  155.  
  156.                    /*===================================*/
  157.                    /*  old_palette is a pointer to the  */
  158.                    /*  allocated memory for palette[]   */
  159.                    /*  and colourarray[]                */
  160.                    /*===================================*/
  161.  
  162.        UWORD         *old_palette  = NULL;
  163.  
  164.                  /*======================================*/
  165.                  /*  Palette[] (note the capital P) is   */
  166.                  /*  used to hold the values of my 5     */
  167.                  /*  palette colours for Talker's face.  */
  168.                  /*======================================*/
  169.  
  170. USHORT Palette[] = {
  171.    0x0620,   /* color #8 */
  172.    0x0c85,   /* color #9 */
  173.    0x0ea8,   /* color #10 */
  174.    0x0fb9,   /* color #11 */
  175.    0x0841,   /* color #12 */
  176. #define PaletteColorCount 5
  177. };
  178.  
  179. #define PALETTE Palette
  180.  
  181. static struct NewWindow NewWindowStructure1 = {
  182.     400,100,    /* window XY origin relative to TopLeft of screen */
  183.     100,86, /* window width and height */
  184.     0,1,    /* detail and block pens */
  185.     CLOSEWINDOW+DISKINSERTED+DISKREMOVED+INTUITICKS+ACTIVEWINDOW, /* IDCMP */
  186.     WINDOWDRAG+WINDOWCLOSE+WINDOWDEPTH+
  187.    WINDOWACTIVE+ACTIVATE+SMART_REFRESH, /* window flags */
  188.     NULL,    /* first gadget in gadget list */
  189.     NULL,    /* custom CHECKMARK imagery */
  190.     (UBYTE *)"][",    /* window title */
  191.     NULL,    /* custom screen pointer */
  192.     NULL,    /* custom bitmap */
  193.     100,86, /* minimum width and height */
  194.     -1,-1, /* maximum width and height  */
  195.     WBENCHSCREEN    /* destination screen type */
  196. };
  197.       /* end of PowerWindows source generation */
  198.  
  199.  
  200.                /*===========================================*/
  201.                /*    CloseWind()  --                        */
  202.                /*-------------------------------------------*/
  203.                /*      This routine is the program's final  */
  204.                /*  exit point. This shuts down all opened   */
  205.                /*  windows, ports, and deallocates all      */
  206.                /*  allocated memory.                        */
  207.                /*===========================================*/
  208.  
  209. VOID
  210. CloseWind(errorstring)
  211.  char *errorstring;
  212.  {
  213.   if(errorstring)
  214.    {
  215.     puts(errorstring);
  216.    };
  217.  
  218.   if(voice_port)
  219.    {
  220.     DeletePort(voice_port);
  221.    };
  222.  
  223.   if(mouth_port)
  224.    {
  225.     DeletePort(mouth_port); 
  226.    };
  227.  
  228.   if(voice_io)
  229.    {
  230.     CloseDevice(voice_io); 
  231.     DeleteExtIO(voice_io); 
  232.    };
  233.  
  234.   if(mouth_io)
  235.    {
  236.     DeleteExtIO(mouth_io);
  237.    };
  238.  
  239.   if(TalkerWindow)
  240.    {
  241.     if(old_palette != NULL)
  242.      {
  243.       restore_screen(old_palette);
  244.       FreeMem(old_palette,(long)(16 * sizeof(UWORD)));
  245.      };
  246.  
  247.     while( mesg = (struct IntuiMessage *)GetMsg(TalkerWindow->UserPort) )
  248.          ReplyMsg(mesg);
  249.     CloseWindow(TalkerWindow);
  250.    };
  251.  
  252.   exit(0);
  253.  }
  254.  
  255.  
  256.            /*===================================================*/
  257.            /*    changestring()   --                            */
  258.            /*---------------------------------------------------*/
  259.            /*      This routine translates the string           */
  260.            /*  passed to it into something the narrator.device  */
  261.            /*  can handle. "in" points to the incoming string,  */
  262.            /*  "out" points to the outgoing string. "inlen"     */
  263.            /*  is the length of the incoming string, "outlen"   */
  264.            /*  is the length of the outgoing string.            */
  265.            /*===================================================*/
  266.  
  267. VOID
  268. changestring(in,inlen,out,outlen)
  269.  UBYTE *in,*out;
  270.  SHORT inlen,outlen;
  271.  {
  272.   if(Translate(in,inlen,out,outlen))
  273.    {
  274.     CloseWind("translation error");
  275.    };
  276.  
  277.  }
  278.  
  279.  
  280.             /*================================================*/
  281.             /*    Blink()  --                                 */
  282.             /*------------------------------------------------*/
  283.             /*      This routine handles the blinking of the  */
  284.             /*  eyes and controls the speed of the blink.     */
  285.             /*================================================*/
  286.  
  287. VOID 
  288. Blink(pauseme)
  289. ULONG pauseme;
  290.  {
  291.   int x;
  292.   for(x = 0; x < 4; x++)
  293.    {
  294.     neweyes = EyeArray[x];
  295.     WaitTOF();
  296.     DrawImage(rast,neweyes,7,15);
  297.     Delay(pauseme);
  298.     };
  299.  
  300.  }
  301.  
  302.  
  303.                  /*=======================================*/
  304.                  /*    Closemouth()  --                   */
  305.                  /*---------------------------------------*/
  306.                  /*      This routine closes the mouth    */
  307.                  /*  after a 'sentence' has been spoken.  */
  308.                  /*  It determines which array to use,    */
  309.                  /*  based upon height vs width.          */
  310.                  /*=======================================*/
  311.  
  312. VOID
  313. Closemouth(high,wide)
  314. UBYTE high,wide;
  315.  {
  316.   ULONG x;
  317.   if(high > wide)
  318.    {
  319.     for(x = high; x > 0; x--)
  320.       {
  321.        WaitTOF();
  322.        DrawImage(rast,HArray[x],7,15);
  323.       };
  324.    };
  325.  
  326.   if(wide >= high)
  327.    {
  328.     for(x = wide; x > 0; x--)
  329.       {
  330.        WaitTOF();
  331.        DrawImage(rast,WArray[x],7,15);
  332.       };
  333.    };
  334.  
  335.  }
  336.  
  337.  
  338.            /*==================================================*/
  339.            /*    NewPalette()  --                              */
  340.            /*--------------------------------------------------*/
  341.            /*      This routine sets up the 5 color registers  */
  342.            /*  used to make the colors of the face. Note that  */
  343.            /*  colors 1 and 2 are used as as well as colors    */
  344.            /*  8-12. Color 1 must be black, color 2 must be    */
  345.            /*  white or it'll look weird.                      */
  346.            /*==================================================*/
  347.  
  348. VOID
  349. NewPalette()
  350.  {
  351.  long x;
  352.  UWORD discolour;
  353.  for(x = 0;x < 5;x++)
  354.    {
  355.     discolour = Palette[x];
  356.     SetRGB4(Vprt,x + 8,((discolour&0xf00)>>8),(discolour&0xf0)>>4,
  357.            (discolour&0x0f));
  358.    };
  359.  
  360.  }
  361.  
  362.  
  363.                /*===========================================*/
  364.                /*     HandleEvent()  --                     */
  365.                /*-------------------------------------------*/
  366.                /*   This routine deals with all events that */
  367.                /* are captured with GetEvents(). It first   */
  368.                /* copies the message into variables, and    */
  369.                /* then calls ReplyMsg() to free up the msg  */
  370.                /* port. It is called from GetEvents(),      */
  371.                /* and returns nothing.                      */
  372.                /*===========================================*/
  373.  
  374. VOID
  375. HandleEvent(EventMessage)
  376.  struct IntuiMessage *EventMessage;
  377.  {
  378.   ULONG  class;
  379.   USHORT code, qual;
  380.   struct Gadget   *address;
  381.   SHORT  MooseX,MooseY;
  382.   struct Window  *disone;
  383.  
  384.   class     = EventMessage->Class;
  385.   code      = EventMessage->Code;
  386.   qual      = EventMessage->Qualifier;
  387.   disone    = EventMessage->IDCMPWindow;
  388.   address   = (struct Gadget *)EventMessage->IAddress;
  389.   MooseX    = EventMessage->MouseX;
  390.   MooseY    = EventMessage->MouseY;
  391.  
  392.   ReplyMsg((struct Message *)EventMessage);
  393.  
  394.   if(class == DISKINSERTED)
  395.    {
  396.     restore_screen(old_palette);
  397.     NewPalette();
  398.    };
  399.  
  400.   if(class == DISKREMOVED)
  401.    {
  402.     blank_screen();
  403.    };
  404.  
  405.   if(class == CLOSEWINDOW)
  406.    {
  407.     CloseWind("We're outta here.\n");
  408.    };
  409.  
  410.  }
  411.  
  412.  
  413.               /*=============================================*/
  414.               /*    GetEvents()                              */
  415.               /*---------------------------------------------*/
  416.               /*       This routine is the loop for getting  */
  417.               /*  and processing Window IDCMP events. It is  */
  418.               /*  affected by clicking on the close gadget,  */
  419.               /*  and by inserting or removing a diskette.   */
  420.               /*  It is called by, and therefore is only     */
  421.               /*  effective through, LookAround(), restore_  */
  422.               /*  screen() and blank_screen.                 */
  423.               /*=============================================*/
  424.  
  425. VOID
  426. GetEvents()
  427.  {
  428.   struct IntuiMessage *EventMsg;
  429.   WaitPort(TalkerWindow->UserPort);
  430.   while(EventMsg = (struct IntuiMessage *)GetMsg(TalkerWindow->UserPort))
  431.        HandleEvent(EventMsg);
  432.  }
  433.  
  434.  
  435.    /*==================================================================*/
  436.    /*    LookAround()  --                                              */
  437.    /*------------------------------------------------------------------*/
  438.    /*      This routine makes the Talker look around awhile. You pass  */
  439.    /*  a value for how long you want it to look around, it uses that   */
  440.    /*  as a seed for the random number generator, and then generates   */
  441.    /*  a random number to determine which way the Talker will look.    */
  442.    /*  The random value will be either 0 or 1 because of the modulo    */
  443.    /*  performed on it. This value is plugged in as the first          */
  444.    /*  dimension of the array LookArray[][], and then a for loop       */
  445.    /*  determines the 2nd dimension This walks you halfway through the */ 
  446.    /*  array, either to the left (number equals zero) or to the right  */
  447.    /*  (number equals 1). It also calls GetEvents() in the middle of   */
  448.    /*  this loop, to determine if the user wishes to blank the screen  */
  449.    /*  (or restore it).                                                */
  450.    /*==================================================================*/
  451.      
  452. VOID
  453. LookAround(waiter)
  454.  int waiter;
  455.  {
  456.  int iterations,disimage,whichway;
  457.  struct Image *newlook;
  458.   srand(waiter);
  459.   for(iterations = 0;iterations < waiter;iterations++)
  460.     {
  461.      whichway = rand() % 2;
  462.      for(disimage = 0;disimage < 6;disimage++)
  463.        {
  464.         newlook = LookArray[whichway][disimage];
  465.         WaitTOF();
  466.         DrawImage(rast,newlook,7,15);
  467.         if(disimage == 3)
  468.          {
  469.           Delay(((rand() % 50) + 1) * 2);
  470.          };
  471.  
  472.         GetEvents();
  473.        };
  474.  
  475.      if(!(rand() % 10))
  476.       {
  477.        Blink(2);
  478.       };
  479.  
  480.      Delay(((rand() % 100) + 1) * 2);
  481.     };
  482.  
  483.  }
  484.  
  485.  
  486.              /*==============================================*/
  487.              /*   talk_to_me()  --                           */
  488.              /*----------------------------------------------*/
  489.              /*      This routine does the actual output of  */
  490.              /*  speech. It sets up the parameters of the    */
  491.              /*  narrator_rb and mouth_rb structures to      */
  492.              /*  output a 'sentence' of speech, as well as   */
  493.              /*  the 'format' of that speech. It then gets   */
  494.              /*  the data for the shape of the Talker's      */
  495.              /*  mouth. That data is a value from 0 to 15    */
  496.              /*  for width, and a value from 0 to 15 for     */
  497.              /*  height.                                     */
  498.              /*==============================================*/
  499.  
  500. VOID
  501. talk_to_me(speech)
  502. char *speech;
  503.  {
  504.   voice_io->message.io_Data = (APTR)speech;
  505.   voice_io->message.io_Length = strlen(speech);
  506.   voice_io->ch_masks = audio_chan;
  507.   voice_io->nm_masks = sizeof(audio_chan);
  508.  
  509.   voice_io->mouths   =     1;
  510.   voice_io->volume   =    64;
  511.   voice_io->rate     =   150;
  512.   voice_io->sex      = MALE;
  513.   voice_io->pitch    = DEFPITCH;
  514.   voice_io->sampfreq = 23000;
  515.   mouth_io->voice.message.io_Error = 0;
  516.  
  517.   SendIO(voice_io);
  518.  
  519.   while(mouth_io->voice.message.io_Error == 0)
  520.       {
  521.        DoIO(mouth_io);
  522.        if(mouth_io->height >= mouth_io->width)
  523.         {
  524.          newmouth = HArray[mouth_io->height];
  525.         }
  526.        else
  527.          {
  528.           newmouth = WArray[mouth_io->width];
  529.          };
  530.  
  531.        WaitTOF();
  532.        DrawImage(rast,newmouth,7,15);
  533.       }
  534.  
  535.   WaitIO(voice_io);
  536.   Closemouth(mouth_io->height,mouth_io->width);
  537.   if(!(rand() % 100))
  538.    {
  539.     LookAround(rand());
  540.    };
  541.  
  542.   if(!(rand() % 10))
  543.    {
  544.     Blink(2);
  545.    };
  546.  
  547.  }
  548.  
  549.              /*===============================================*/
  550.              /*    prep_to_talk()  --                         */
  551.              /*-----------------------------------------------*/
  552.              /*      This routine initializes the system to   */
  553.              /*  speak. It creates and initializes the audio  */
  554.              /*  message port, and the 'video' message port,  */
  555.              /*  the port we use to get the mouth shapes.     */
  556.              /*===============================================*/
  557.  
  558. int
  559. prep_to_talk()
  560. {
  561.  if((voice_port = (struct MsgPort *)CreatePort(0,0)) == NULL)
  562.   {
  563.    return(ERR);
  564.   };
  565.  
  566.  if((mouth_port = (struct MsgPort *)CreatePort(0L,0L)) == NULL)
  567.   {
  568.    return(ERR);
  569.   };
  570.  
  571.  if((voice_io = (struct narrator_rb *)
  572.  CreateExtIO(voice_port,sizeof(struct narrator_rb))) == NULL)
  573.   {
  574.    return(ERR);
  575.   };
  576.  
  577.  if((mouth_io = (struct mouth_rb *)
  578.  CreateExtIO(mouth_port,sizeof(struct mouth_rb))) == NULL)
  579.   {
  580.    return(ERR);
  581.   };
  582.  
  583.  voice_io->message.io_Command=CMD_WRITE;
  584.  
  585.  if(OpenDevice("narrator.device",0L,voice_io,0L) != 0L)
  586.   {
  587.    return(ERR);
  588.   };
  589.  
  590.  mouth_io->voice.message.io_Device=voice_io->message.io_Device;
  591.  mouth_io->voice.message.io_Unit=voice_io->message.io_Unit;
  592.  mouth_io->width = 0;
  593.  mouth_io->height = 0;
  594.  mouth_io->voice.message.io_Command = CMD_READ;
  595.  mouth_io->voice.message.io_Error = 0;
  596.  return(SUCCESS);
  597.  
  598. }
  599.  
  600.          /*======================================================*/
  601.          /*    OpenLibs()  --                                    */
  602.          /*------------------------------------------------------*/
  603.          /*      This routine opens all the libraries accessed   */
  604.          /*  by the program. It bails out with an error message  */
  605.          /*  if it cannot open any of the libraries.             */
  606.          /*======================================================*/
  607.  
  608. VOID
  609. OpenLibs()
  610.  {
  611.   TranslatorBase = OpenLibrary("translator.library",REV);
  612.   if(TranslatorBase == NULL)
  613.    {
  614.     CloseWind("couldn't open translator library");
  615.    };
  616.  
  617.   IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library",0);
  618.   if(IntuitionBase == NULL)
  619.    {
  620.     CloseWind("couldn't open Intuition library");
  621.    };
  622.  
  623.   GfxBase = (struct GfxBase *)OpenLibrary("graphics.library",0);
  624.   if(GfxBase == NULL)
  625.    {
  626.     CloseWind("couldn't open Graphics library");
  627.    };
  628.  
  629.  }
  630.  
  631.  
  632.  
  633. int
  634. Preserve_Colours(colourarray)
  635.  UWORD colourarray[16];
  636.  {
  637.  long x;
  638.   for(x = 0;x < 16; x++)
  639.     {
  640.      if((colourarray[x] = GetRGB4(Vprt->ColorMap,x)) < 0)
  641.       {
  642.        CloseWind("couldn't save old palette, sorry");
  643.       };
  644.     };
  645.  
  646.   return(1);
  647.  }
  648.  
  649.         /*=========================================================*/
  650.         /*    restore_screen() --                                  */
  651.         /*---------------------------------------------------------*/
  652.         /*      This routine restores the workbench's _original_   */
  653.         /*  palette in its entirety. Which means that the colors   */
  654.         /*  used to draw the Talker will revert to their original  */
  655.         /*  values. It does the restore by incrementing the value  */
  656.         /*  of 16 color registers until each is equal to its       */
  657.         /*  original value, preserved (via PreserveColours()) by   */
  658.         /*  the array pointed at by old_palette.                   */
  659.         /*=========================================================*/
  660.  
  661. restore_screen(palette)
  662.  UWORD palette[16];
  663.  {
  664.  long discolour,x,y;
  665.   for(x = 0;x < 16;x++)
  666.     {
  667.      for(y = 0;y < 16;y++)
  668.        {
  669.         discolour = GetRGB4(Vprt->ColorMap,y);
  670.         discolour += 273;
  671.  
  672.         if(discolour > (long)palette[y])
  673.          {
  674.           discolour = (long)palette[y];
  675.          };
  676.  
  677.         SetRGB4(Vprt,y,((discolour&0xf00)>>8),(discolour&0xf0)>>4,
  678.                (discolour&0x0f));
  679.        };
  680.  
  681.      Delay(x);
  682.     };
  683.  }
  684.  
  685.             /*=================================================*/
  686.             /*    blank_screen()  --                           */
  687.             /*-------------------------------------------------*/
  688.             /*      This routine fades the screen colours      */
  689.             /*  to black. Note that this does not affect the   */
  690.             /*  pointer, because the colour registers          */
  691.             /*  themselves are unaffected (I think that's      */
  692.             /*  why :). It works the opposite of restore_      */
  693.             /*  screen(), in that colors are decremented       */
  694.             /*  til they reach zero. Note the majick number:   */
  695.             /*  273, which is 0x0111 hex, or 0000000100010001  */
  696.             /*  in binary. Since the r-g-b values are stored   */
  697.             /*  with r having a value of 0-15 times 2^8th, g   */
  698.             /*  having a value of 0-15 times 2^4th, and then   */
  699.             /*  b having a value of 0-15 times 2^0th, in a     */
  700.             /*  long value (top 4 bits are ignored), the       */
  701.             /*  majick number will subtract 1 from each r-g-b  */
  702.             /*  value. Subtracting one would only change the   */
  703.             /*  b value, which will mess things up once you    */
  704.             /*  do the shift (in SetRGB4()).                   */
  705.             /*=================================================*/
  706.  
  707. blank_screen()
  708.  {
  709.  long discolour,x,y;
  710.   for(x = 0;x < 16;x++)
  711.     {
  712.      for(y = 0;y < 16;y++)
  713.        {
  714.         discolour = GetRGB4(Vprt->ColorMap,y);
  715.         discolour -= (long)273;
  716.  
  717.         if(discolour < (long)0)
  718.          {
  719.           discolour = (long)0;
  720.          };
  721.  
  722.         SetRGB4(Vprt,y,((discolour&0xf00)>>8),(discolour&0xf0)>>4,
  723.                (discolour&0x0f));
  724.        };
  725.  
  726.      Delay(x);
  727.     };
  728.  }
  729.  
  730.  
  731.           /*====================================================*/
  732.           /*    OpenWind()  --                                  */
  733.           /*----------------------------------------------------*/
  734.           /*      This routine opens the window which contains  */
  735.           /*  the Talker imagery. It also allocates the memory  */
  736.           /*  for the array of values for the old palette, and  */
  737.           /*  points old_palette at it. It then saves the  old  */
  738.           /*  colours (via Preserve_Colours()), and sets up a   */
  739.           /*  new palette using the 5 colours in Palette[]. It  */
  740.           /*  then draws the initial facial image.              */
  741.           /*====================================================*/
  742.  
  743. VOID
  744. OpenWind()
  745.  {
  746.   if((TalkerWindow = (struct Window *)OpenWindow(&NewWindowStructure1)) == NULL)
  747.    {
  748.     CloseWind("Couldn't Open window");
  749.    };
  750.  
  751.   Vprt = (struct ViewPort *)ViewPortAddress(TalkerWindow);
  752.   if((old_palette = (UWORD *)AllocMem(sizeof(UWORD) * 16,MEMF_CLEAR)) != NULL)
  753.    {
  754.     if(Preserve_Colours(old_palette) == NULL)
  755.      {
  756.       CloseWind("Can't restore old palette");
  757.      };
  758.  
  759.       NewPalette();
  760.    };
  761.   rast = TalkerWindow->RPort;
  762.   WaitTOF();
  763.   DrawImage(rast,&face0_Image,7,15);
  764.  
  765.  }
  766.  
  767.  
  768.  
  769.  
  770.                    /*===================================*/
  771.                    /*    enter_text()  --               */
  772.                    /*-----------------------------------*/
  773.                    /*      This routine is called when  */
  774.                    /*  TalkerII is invoked without any  */
  775.                    /*  command line arguments. It       */
  776.                    /*  prompts the user for text to be  */
  777.                    /*  spoken, then speaks that text.   */
  778.                    /*===================================*/
  779.  
  780. VOID
  781. enter_text()
  782.  { 
  783.   Delay(25);
  784.   printf("enter string: ");
  785.   gets(in_string);
  786.   Delay(10);
  787.   Blink(10L);
  788.   changestring(in_string,strlen(in_string),out_string,1024L);
  789.   Delay(5);
  790.   Blink(5L);
  791.   talk_to_me(out_string);
  792.  
  793.  }
  794.  
  795.  
  796.                 /*=========================================*/
  797.                 /*    say_file()  --                       */
  798.                 /*-----------------------------------------*/
  799.                 /*      This routine speaks the text in a  */
  800.                 /*  file. It opens the file given in the   */
  801.                 /*  command line argument(s), translates   */
  802.                 /*  the text, and outputs it.              */
  803.                 /*=========================================*/
  804.  
  805. VOID
  806. say_file(name)
  807. char *name;
  808.  {
  809.   FILE   *f;      /* file pointer */
  810.   if((f = fopen(name,"r")) == NULL)
  811.    {
  812.     CloseWind("can't open file\n" );
  813.    };
  814.   while(fgets(in_string,255,f) != 0L)
  815.       {
  816.        changestring(in_string,(long)strlen(in_string),out_string,1024L); 
  817.        talk_to_me(&out_string);
  818.       };
  819.  
  820.  }
  821.  
  822.  
  823.                 /*========================================*/
  824.                 /*    Howlong()  --                       */
  825.                 /*----------------------------------------*/
  826.                 /*      This routine determines how long  */
  827.                 /*  the Talker should look around before  */
  828.                 /*  speaking the file.                    */
  829.                 /*========================================*/
  830.  
  831. int
  832. Howlong(timerstring)
  833.  char *timerstring;
  834.  {
  835.  int i;
  836.   i = atoi((timerstring + 2));
  837.   return(i);
  838.  }
  839.  
  840.  
  841. main(argc,argv)
  842.  int argc;
  843.  char *argv[];
  844.  {
  845.   OpenLibs();
  846.   OpenWind();
  847.   prep_to_talk();
  848.  
  849.   if(!argv[1])
  850.    {
  851.     enter_text();
  852.    }
  853.   else if(strncmp(argv[1],"-l",2) == NULL)
  854.         {
  855.          LookAround(Howlong(argv[1]));
  856.          Blink(5);
  857.          if(argv[2])
  858.           {
  859.            say_file(argv[2]);
  860.           };
  861.         }
  862.       else
  863.         {
  864.          Blink(5);
  865.          say_file(argv[1]);
  866.         };
  867.  
  868.   Delay(25);
  869.   CloseWind(NULL);
  870.  }
  871.