home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 127.lha / Anim / grabanim.c < prev    next >
C/C++ Source or Header  |  1986-11-20  |  19KB  |  565 lines

  1.  
  2. /*  GrabAnim.c
  3.  * 
  4.  * This program was created from IFFEncode which was obtained
  5.  * from Fish disk #38.
  6.  *
  7.  * Grabanim permits sequences of graphic screens to be grabbed (the highest
  8.  * screen is used) and output to disk in IFF ANIM format.  GrabANIM is designed
  9.  * to run as a task on the Amiga and to "grab" graphic screens and add them
  10.  * to an open ANIM file.  GrabANIM may be controlled either from the CLI or
  11.  * with a controller inserted into the second game port.  Most controllers
  12.  * in use on the Amiga will work including another Amiga mouse, a joystick,
  13.  * or even a Koala pad (don't laugh, it has good quality buttons).  One
  14.  * criteria of a controller are good buttons, since I didn't provide any
  15.  * de-bouncing code.  Old Atari joysticks will usually not work well, giving
  16.  * multiple reports for each try.  The nicest controller is to buy or build
  17.  * a box, with good buttons, that simply provides button input to the up, down,
  18.  * left, and right joystick directions.  Along with this, three more buttons
  19.  * may be added for the left, middle, and right mouse buttons for a total
  20.  * of seven (7) buttons of control off one game port (yes, the Amiga operating
  21.  * system supports a middle mouse button even though there isn't one 
  22.  * available at present).  When using such a controller, one can press the
  23.  * correct button whenever he wants to "grab" the current graphic screen to
  24.  * an open ANIM file.  Just follow the prompts, it isn't bad.
  25.  *
  26.  * To use GrabANIM, simply open a new CLI screen (via newcli, newshell, etc.)
  27.  * and enter the command "grabanim".  One can then select the method of control
  28.  * by responding to interactive prompts on GrabANIMs CLI screen.
  29.  *
  30.  * In addition, two methods are provided for determining which bitmap to grab.
  31.  * Each may work best in a given situation.  The second one was originally
  32.  * added as the first would not work with the player for Juggler.
  33.  *
  34.  * This version only saves ANIMs in the RIFF style compression technique.
  35.  * The enclosed code (skip.c) for compressing was written and placed
  36.  * in the public domain by Jim Kent.
  37.  *
  38.  * CAUTION!! GrabAnim ASSUMES you will be collecting screens with the same
  39.  * size, depth, colors, etc.  GrabAnim may cause nice fireworks if these
  40.  * assumptions are violated!!
  41.  *
  42.  * GrabAnim was created (from iffencode)
  43.  *    by Gary Bonham, SPARTA, Inc.,
  44.  *    Laguna Hills, Calif.
  45.  * Screen-Finding routine taken from Carolyn's Printer Dump source.
  46.  *
  47.  * The code was stripped of excess stuff in Feb 88 for release as freely
  48.  * distributable software.  The intent was to provide an example of ANIM
  49.  * compression code for other developers.  Since there were a number of
  50.  * different compression techniques in GrabANIM prior to this purge, there
  51.  * will be remenants of this code which inadvertently was not removed.
  52.  * The result, however, is a functional piece of software.
  53.  *
  54.  */
  55.  
  56. #include <exec/types.h>
  57. #include <exec/memory.h>
  58. #include <libraries/dos.h>
  59. #include <graphics/gfxbase.h>
  60. #include <graphics/rastport.h>
  61. #include <graphics/gfx.h>
  62. #include "exec/devices.h"
  63. #include "devices/gameport.h"
  64. #include "devices/inputevent.h"
  65. #include <graphics/view.h>
  66. #include "functions.h"
  67.  
  68. #include <intuition/intuition.h>
  69. #include <intuition/intuitionbase.h>
  70.  
  71. typedef struct IntuitionBase  IBASE;
  72. typedef struct GfxBase        GFXBASE;
  73. typedef struct Window         WIN;
  74. typedef struct Screen         SCR;
  75. typedef struct ViewPort       VP;
  76. typedef struct RastPort       RP;
  77. typedef struct ColorMap       CM;
  78. typedef struct BitMap         BM;
  79.  
  80. IBASE    *IntuitionBase;
  81. GFXBASE  *GfxBase;
  82. struct BitMap *mybitmap[4];
  83. struct BitMap bitmap2,bitmap3,bitmap4;
  84. int Pop,datasize;
  85. LONG *DeltaData,mxDeltaData,nDeltaData;
  86. int SignalX,ActiveW;
  87.  
  88. struct InputEvent *gamedata;
  89. struct IOStdReq *gameiomsg;
  90. struct MsgPort *gamemsgport;
  91. BYTE buffer[sizeof(struct InputEvent)];
  92. BYTE *buff;
  93. static long rastersize;
  94. RP *rp;
  95.  
  96. /* ================================================ */
  97.  
  98. main(ac, av)
  99. char *av[];
  100. {
  101.    char notdone = 1;
  102.    char buf[80];
  103.    char flags = 0;
  104.    int fileopen,i,mouse,datamode,frameno;
  105.    int forbidpermit;
  106.    VP *vp;
  107.    CM *cm;
  108.  
  109.    forbidpermit = 0;
  110.    SignalX = 1; /* default to a visible signal after frame is recorded */
  111.    if ((IntuitionBase=(IBASE *)OpenLibrary("intuition.library",0L)) == NULL)
  112.       cleanexit("Can't open Intuition.");
  113.    if ((GfxBase=(GFXBASE *)OpenLibrary("graphics.library",0L)) == NULL)
  114.       cleanexit("Can't open Graphics.");
  115.  
  116.    puts ("Animation file screen grab program - ver. 2.00\n");
  117.  
  118.    ActiveW = 0;
  119.    DeltaData = 0;
  120.    datamode = 0;
  121.    datasize = 2;
  122.    gamemsgport = 0;
  123.    gameiomsg = 0;
  124.    fileopen = 0;
  125.    Pop = 0;
  126.    while(notdone) {
  127.       puts("SELECT:   (J)oystick          (O)pen anim");
  128.       puts("          (M)ouse             (A)dd to anim");
  129.       puts("          (K)oala pad         (C)lose anim");
  130.       puts("          (P) to turn off multicolor signal stripe");
  131.       puts("          ($) to change from top screen to active scr/window");
  132.       puts("          (Q) to quit.");
  133.       mouse = 0;
  134.       switch (getch()) {
  135.       case '$':
  136.          puts("Use Active window for capture");
  137.          ActiveW = 1;
  138.          break;
  139.       case 'P':
  140.          puts("Visible record signal disabled");
  141.          SignalX = 0;
  142.          break;
  143.       case 'K':
  144.          mouse++;  /* double-inc of mouse to =2 for Koala pad buttons */
  145.       case 'M':
  146.          mouse++;  /* single-inc of mouse to =1 for mouse buttons */
  147.       case 'J':
  148.          if (fileopen) {
  149.             printf("Close file, %d frames\n",frameno);
  150.             CloseAnimationFile();
  151.             fileopen = 0;
  152.          }
  153.          puts("Enter file name (blank to abort):"); 
  154.          gets(buf);
  155.          if (buf[0]) {
  156.             if (mouse==1) {
  157.                puts("LH mouse button   - add file");
  158.                puts("RH mouse button   - close file");
  159.             }
  160.             else if (mouse==2) {
  161.                puts("LH Koala button   - add file");
  162.                puts("RH Koala button   - close file");
  163.             }
  164.             else {
  165.                puts("Joystick fire  - add file");
  166.                puts("Joystick up    - close file");
  167.                puts("Joystick left  - forbid");
  168.                puts("Joystick down  - permit");
  169.             }
  170.             buff = &buffer[0];
  171.             if ((gamemsgport = CreatePort(0L,0L)) == 0)
  172.                cleanexit("Error - CreatePort");
  173.             if ((gameiomsg = CreateStdIO(gamemsgport)) == 0)
  174.                cleanexit("Error - CreateStdIO");
  175.             if (OpenDevice("gameport.device",1L,gameiomsg,0L))
  176.                cleanexit("Error - OpenDevice");
  177.             gamedata = (struct InputEvent *)buffer;
  178.             if (SetControllerType((long)GPCT_ABSJOYSTICK))
  179.                cleanexit("Error - SetControllerType");
  180.             if (SetControllerTrigger())
  181.                cleanexit("Error - SetControllerTrigger");
  182.             gameiomsg->io_Command = GPD_READEVENT;
  183.             gameiomsg->io_Data = (APTR)buffer;
  184.             gameiomsg->io_Length = sizeof(struct InputEvent);
  185.             gameiomsg->io_Flags = 0;
  186.             frameno = 0;
  187.             FOREVER {
  188.                SendIO(gameiomsg);
  189.                if (forbidpermit == 0) WaitPort(gamemsgport);
  190.                GetMsg(gamemsgport);
  191.  
  192.                /* fire button or LH mouse button - add screen to file */
  193.                if (((mouse != 2) && (gamedata->ie_Code == IECODE_LBUTTON))
  194.                   || ((mouse == 2) && (gamedata->ie_X == -1))) {
  195.                   if (fileopen == 0) { /* open anim file */
  196.                      getPointers(&vp, &cm, &rp);
  197.                      mybitmap[0] = rp->BitMap;
  198.                      OpenBitmaps((int)rp->BitMap->BytesPerRow<<3
  199.                                 ,(int)rp->BitMap->Rows
  200.                                 ,(int)rp->BitMap->Depth);
  201.                      GenViewCopy(0,1);
  202.                      DisplayBeep(0L);
  203.                      DisplayBeep(0L);
  204.                      if (SignalX) { /* multi-color stripe to signal done */
  205.                         for (i=500;i<700;i++) {
  206.                            if (mybitmap[0]->Planes[0])
  207.                               *((LONG *)mybitmap[0]->Planes[0]+i) = 0xCCCCCCCC;
  208.                            if (mybitmap[0]->Planes[1])
  209.                               *((LONG *)mybitmap[0]->Planes[1]+i) = 0xF0F0F0F0;
  210.                            if (mybitmap[0]->Planes[2])
  211.                               *((LONG *)mybitmap[0]->Planes[2]+i) = 0xFF00FF00;
  212.                            if (mybitmap[0]->Planes[3])
  213.                               *((LONG *)mybitmap[0]->Planes[3]+i) = 0xFFFF0000;
  214.                         }
  215.                      }
  216.                      GenViewCopy(1,2);
  217.                      OpenAnimationFile(1,buf,cm,vp);
  218.                      fileopen = 1;
  219.                      frameno++;
  220.                   }
  221.                   else { /* add to anim file */
  222.                      frameno++;
  223.                      getPointers(&vp, &cm, &rp);
  224.                      mybitmap[0] = rp->BitMap;
  225.                      GenViewCopy(2,3);
  226.                      GenViewCopy(1,2);
  227.                      GenViewCopy(0,1);
  228.                      DisplayBeep(0L);
  229.                      DisplayBeep(0L);
  230.                      if (SignalX) {
  231.                         for (i=500;i<700;i++) {
  232.                            if (mybitmap[0]->Planes[0])
  233.                               *((LONG *)mybitmap[0]->Planes[0]+i) = 0xCCCCCCCC;
  234.                            if (mybitmap[0]->Planes[1])
  235.                               *((LONG *)mybitmap[0]->Planes[1]+i) = 0xF0F0F0F0;
  236.                            if (mybitmap[0]->Planes[2])
  237.                               *((LONG *)mybitmap[0]->Planes[2]+i) = 0xFF00FF00;
  238.                            if (mybitmap[0]->Planes[3])
  239.                               *((LONG *)mybitmap[0]->Planes[3]+i) = 0xFFFF0000;
  240.                         }
  241.                      }
  242.                      printf("frame %d\n",frameno);
  243.                      FormRIFF(1,3);
  244.                      AddAnimationFrame2(DeltaData,nDeltaData,5);
  245.                      if (DeltaData) FreeMem(DeltaData,nDeltaData);
  246.                      DeltaData = 0;
  247.                   }
  248.                }
  249.                /* up button or RH mouse button - close file */
  250.                else if (((mouse == 1) && (gamedata->ie_Code == IECODE_RBUTTON))
  251.                      || ((mouse == 0) && (gamedata->ie_Y == -1))
  252.                      || ((mouse == 2) && (gamedata->ie_X ==  1))) {
  253.                   if (fileopen) {
  254.                      printf("Close file, %d frames\n",frameno);
  255.                      CloseAnimationFile();
  256.                      DisplayBeep(0L);
  257.                      DisplayBeep(0L);
  258.                      fileopen = 0;
  259.                   }
  260.                   SetControllerType((long)GPCT_NOCONTROLLER);
  261.                   CloseDevice(gameiomsg);
  262.                   DeleteStdIO(gameiomsg);
  263.                   gameiomsg = 0;
  264.                   DeletePort(gamemsgport);
  265.                   gamemsgport = 0;
  266.                   break;
  267.                }
  268.                /* left joystick button - forbid */
  269.                else if (((mouse == 0) && (gamedata->ie_X == -1))) {
  270.                   if (forbidpermit == 0) {
  271.                      forbidpermit = 1;
  272.                      Forbid();
  273.                      printf("##### FORBID #####\n");
  274.                   }
  275.                }
  276.                /* down joystick button - permit */
  277.                else if (((mouse == 0) && (gamedata->ie_Y == 1))) {
  278.                   if (forbidpermit) {
  279.                      forbidpermit = 0;
  280.                      Permit();
  281.                      printf("##### PERMIT #####\n");
  282.                   }
  283.                }
  284.             }
  285.          }
  286.          break;
  287.       case 'O':
  288.          if (fileopen) {
  289.             printf("Close file, %d frames\n",frameno);
  290.             CloseAnimationFile();
  291.             fileopen = 0;
  292.          }
  293.          puts("Enter file name (blank to abort):"); 
  294.          gets(buf);
  295.          frameno = 1;
  296.          if (buf[0]) {
  297.             do_imopts(&vp, &cm, &rp);
  298.             mybitmap[0] = rp->BitMap;
  299.             OpenBitmaps((int)rp->BitMap->BytesPerRow<<3
  300.                        ,(int)rp->BitMap->Rows
  301.                        ,(int)rp->BitMap->Depth);
  302.             GenViewCopy(0,1);
  303.             DisplayBeep(0L);
  304.             DisplayBeep(0L);
  305.             GenViewCopy(1,2);
  306.             OpenAnimationFile(1,buf,cm,vp);
  307.             fileopen = 1;
  308.             puts("done with frame");
  309.          }
  310.          break;
  311.       case 'A':
  312.          if (fileopen) {
  313.             do_imopts(&vp, &cm, &rp);
  314.             mybitmap[0] = rp->BitMap;
  315.             GenViewCopy(2,3);
  316.             GenViewCopy(1,2);
  317.             GenViewCopy(0,1);
  318.             DisplayBeep(0L);
  319.             DisplayBeep(0L);
  320.             puts("done with frame");
  321.             printf("frame %d\n",frameno);
  322.             FormRIFF(1,3);
  323.             AddAnimationFrame2(DeltaData,nDeltaData,5);
  324.             if (DeltaData) FreeMem(DeltaData,nDeltaData);
  325.             DeltaData = 0;
  326.          }
  327.          break;
  328.       case 'Q':
  329.          notdone = 0;
  330.       case 'C':
  331.          if (fileopen) {
  332.             printf("Close file, %d frames\n",frameno);
  333.             CloseAnimationFile();
  334.             DisplayBeep(0L);
  335.             DisplayBeep(0L);
  336.             fileopen = 0;
  337.          }
  338.          break;
  339.       }
  340.    }
  341.    cleanup();
  342. }
  343.  
  344. SetControllerType(type)
  345. long type;
  346. {
  347.    gameiomsg->io_Command = GPD_SETCTYPE;
  348.    gameiomsg->io_Length = 1;
  349.    gameiomsg->io_Data = (APTR)buff;
  350.    *buff = type;
  351.    SendIO(gameiomsg);
  352.    WaitPort(gamemsgport);
  353.    GetMsg(gamemsgport);
  354.    return((int)gameiomsg->io_Error);
  355. }
  356.  
  357. SetControllerTrigger()
  358. {
  359.    struct GamePortTrigger gpt;
  360.    gameiomsg->io_Command = GPD_SETTRIGGER;
  361.    gameiomsg->io_Length = sizeof(gpt);
  362.    gameiomsg->io_Data = (APTR)&gpt;
  363.    gpt.gpt_Keys = GPTF_UPKEYS+GPTF_DOWNKEYS;
  364.    gpt.gpt_Timeout = 0;
  365.    gpt.gpt_XDelta = 1;
  366.    gpt.gpt_YDelta = 1;
  367.    return(DoIO(gameiomsg));
  368. }
  369.  
  370. GenViewCopy(sbuf,nbuf)
  371. int sbuf,nbuf;
  372. {
  373.    register LONG nl,i,*ss,*dd;
  374.    int ip,Width,Height,Depth;
  375.  
  376.    Width = mybitmap[sbuf]->BytesPerRow <<3;
  377.    Height = mybitmap[sbuf]->Rows;
  378.    Depth = mybitmap[sbuf]->Depth;
  379.  
  380.    nl =    ((long)Width * (long)Height) >>5; /* convert bits to longs */
  381.    for (ip=0;ip<Depth;ip++) {
  382.       ss = (LONG *)mybitmap[sbuf]->Planes[ip];
  383.       dd = (LONG *)mybitmap[nbuf]->Planes[ip];
  384.  
  385.       for (i=0;i<nl;i++) {
  386.          *dd = *ss;
  387.          dd++;
  388.          ss++;
  389.       }
  390.    }
  391.    return(0);
  392. }
  393.  
  394. FreeBitmaps()
  395. {
  396.    int i;
  397.    if (DeltaData) FreeMem(DeltaData,mxDeltaData);
  398.    for (i=0;i<6;i++) {
  399.       if (bitmap2.Planes[i]) FreeMem(bitmap2.Planes[i],rastersize);
  400.       if (bitmap3.Planes[i]) FreeMem(bitmap3.Planes[i],rastersize);
  401.       if (bitmap4.Planes[i]) FreeMem(bitmap4.Planes[i],rastersize);
  402.    }
  403.    return(0);
  404. }
  405.  
  406. OpenBitmaps(Width,Height,Depth)
  407. int Width,Height,Depth;
  408. {
  409.    int i;
  410.    for (i=0;i<6;i++) {
  411.       bitmap2.Planes[i] = 0;
  412.       bitmap3.Planes[i] = 0;
  413.       bitmap4.Planes[i] = 0;
  414.    }
  415.    rastersize = ((long)Width*(long)Height)>>3;
  416.    InitBitMap(&bitmap2,(long)Depth,(long)Width,(long)Height);
  417.    for (i=0;i<Depth;i++) {
  418.       bitmap2.Planes[i] = (PLANEPTR)AllocMem(rastersize,(long)MEMF_CLEAR);
  419.       if (bitmap2.Planes[i] == NULL) {
  420.          cleanexit("Not enough room for bitmap2");
  421.       }
  422.    }
  423.    InitBitMap(&bitmap3,(long)Depth,(long)Width,(long)Height);
  424.    for (i=0;i<Depth;i++) {
  425.       bitmap3.Planes[i] = (PLANEPTR)AllocMem(rastersize,(long)(MEMF_CLEAR));
  426.       if (bitmap3.Planes[i] == NULL) {
  427.          cleanexit("Not enough room for bitmap3");
  428.       }
  429.    }
  430.    InitBitMap(&bitmap4,(long)Depth,(long)Width,(long)Height);
  431.    for (i=0;i<Depth;i++) {
  432.       bitmap4.Planes[i] = (PLANEPTR)AllocMem(rastersize,(long)MEMF_CLEAR);
  433.       if (bitmap4.Planes[i] == NULL) {
  434.          cleanexit("Not enough room for bitmap4");
  435.       }
  436.    }
  437.    mybitmap[1] = &bitmap2;
  438.    mybitmap[2] = &bitmap3;
  439.    mybitmap[3] = &bitmap4;
  440.    return(0);
  441. }
  442.  
  443. do_imopts(r_vp, r_cm, r_rp)
  444. VP **r_vp;
  445. CM **r_cm;
  446. RP **r_rp;
  447. {
  448.    puts("Move Screens so Screen to grab is highest.");
  449.    puts("press <RET> when ready:");
  450.    getch();
  451.    getPointers(r_vp, r_cm, r_rp);
  452. }
  453.  
  454.  
  455. getPointers(r_vp, r_cm, r_rp)
  456. VP **r_vp;
  457. CM **r_cm;
  458. RP **r_rp;
  459. {
  460.    SCR *firstscreen, *nextscreen, *highscreen;
  461.    int topEdge;
  462.  
  463.    Forbid();
  464.    firstscreen  = IntuitionBase->FirstScreen;
  465.    topEdge = 9999;
  466.    nextscreen = highscreen = firstscreen;
  467.    while(nextscreen) {
  468.       if(nextscreen->TopEdge < topEdge) {
  469.          topEdge = nextscreen->TopEdge;
  470.          highscreen = nextscreen;
  471.       }
  472.       nextscreen = nextscreen->NextScreen;
  473.    }
  474.    Permit();
  475.  
  476.    *r_vp = &(highscreen->ViewPort);
  477.    *r_cm = (*r_vp)->ColorMap;
  478.    if (ActiveW){
  479.       *r_rp = IntuitionBase->ActiveWindow->RPort;
  480.    }
  481.    else {
  482.       *r_rp = &(highscreen->RastPort);
  483.    }
  484. }
  485.  
  486.  
  487. getch()
  488. {
  489.    char scr[80];
  490.    if (gets(scr)) {
  491.       if (scr[0] >= 'a' && scr[0] <= 'z')
  492.          scr[0] = scr[0] - 'a' + 'A';
  493.       return ((int)scr[0]);
  494.    }
  495.    return(' ');
  496. }
  497.  
  498. cleanexit(errMsg)
  499. char *errMsg;
  500. {
  501.    puts(errMsg);
  502.    cleanup();
  503.    exit(-1);
  504. }
  505.  
  506. cleanup()
  507. {
  508.    FreeBitmaps();
  509.    if (gameiomsg)         DeleteStdIO(gameiomsg);
  510.    if (gamemsgport)       DeletePort(gamemsgport);
  511.    if (IntuitionBase)     CloseLibrary(IntuitionBase);
  512.    if (GfxBase)           CloseLibrary(GfxBase);
  513. }
  514.  
  515. /*** FormRIFF(newbuf,oldbuf) ***/
  516.  
  517. FormRIFF(newbuf,oldbuf)
  518. int newbuf,oldbuf;
  519. {
  520.    unsigned char *outstuff;
  521.    long j,jj[8],nBpP,ib,nb;
  522.    int i;
  523.    int nBpR,nRpP;
  524.    unsigned char *skip_comp_plane();
  525.  
  526.    nBpR = mybitmap[newbuf]->BytesPerRow;
  527.    nRpP = mybitmap[newbuf]->Rows;
  528.    nBpP = (long)nBpR * (long)nRpP;
  529.    j = 64;
  530.    for (i=0;i<mybitmap[newbuf]->Depth;i++) {
  531.       nb = 0;
  532.       for (ib=0;ib<nBpP;ib++)
  533.          if (*(mybitmap[newbuf]->Planes[i]+ib) !=
  534.              *(mybitmap[oldbuf]->Planes[i]+ib)) nb++;
  535.       if (nb) {
  536.          jj[i] = skip_count_plane(mybitmap[newbuf]->Planes[i]
  537.                              ,mybitmap[oldbuf]->Planes[i]
  538.                              ,nBpR,nRpP);
  539.          j += jj[i];
  540.       }
  541.       else jj[i] = 0;
  542.    }
  543.    if ((DeltaData = AllocMem(j,0L)) == 0) {
  544.       printf("Not enough room for ANIM frame deltas\n");
  545.       return(1);
  546.    }
  547.    outstuff = (unsigned char *)(&DeltaData[16]);
  548.    for (i=0;i<16;i++) DeltaData[i] = 0;
  549.    nDeltaData = 64;
  550.    for (i=0;i<mybitmap[newbuf]->Depth;i++) {
  551.       if (jj[i]) {
  552.          DeltaData[i] = nDeltaData;
  553.          nDeltaData += jj[i];
  554.          outstuff = skip_comp_plane(mybitmap[newbuf]->Planes[i]
  555.                           ,mybitmap[oldbuf]->Planes[i]
  556.                           ,outstuff
  557.                           ,nBpR,nRpP);
  558.       }
  559.       else {
  560.          DeltaData[i] = 0;
  561.       }
  562.    }
  563.    return(0);
  564. }
  565.