home *** CD-ROM | disk | FTP | other *** search
/ ProfitPress Mega CDROM2 …eeware (MSDOS)(1992)(Eng) / ProfitPress-MegaCDROM2.B6I / GRAPHICS / MISC / PVQUAN15.ZIP / ANIM.ZIP / ANIM.C next >
Encoding:
C/C++ Source or Header  |  1992-04-01  |  11.8 KB  |  432 lines

  1. /************************************************************************
  2.  *                                                                      *
  3.  *                  Copyright (c) 1992, Frank van der Hulst             *
  4.  *                          All Rights Reserved                         *
  5.  *                                                                      *
  6.  ************************************************************************
  7.  *                                                                      *
  8.  * Authors:                                                             *
  9.  *        FvdH - Frank van der Hulst (Wellington, NZ)                   *
  10.  *                                                                      *
  11.  * Versions:                                                            *
  12.  *    V1.0 911031 FvdH - Released as part of PVQUAN13.ZIP               *
  13.  *    V1.4 920306 FvdH - Improved usage information (PVQUAN14.ZIP)      *
  14.  *                                                                      *
  15.  ************************************************************************/
  16.  
  17. /*
  18.     This program produces animation on a 320*200 screen using page flipping.
  19.     The first command line parameter must be a standard 2D file containing the
  20.     first image. The following files are produced by DIFF, and contain
  21.     information about the differences between alternate images.
  22. */
  23.  
  24. #include <stdlib.h>
  25. #include <stdio.h>
  26. #include <conio.h>
  27. #include <dos.h>
  28. #include <alloc.h>
  29. #include <string.h>
  30. #include <ctype.h>
  31.  
  32. #define FALSE 0
  33. #define TRUE 1
  34.  
  35. #define    UINT    unsigned int
  36.  
  37. #include "xmslib.h"
  38. #include "emslib.h"
  39. #include "gif_lib.h"
  40. #include "vga.h"
  41.  
  42. #define MAX_IMAGES 50
  43.  
  44. #define SC_INDEX           0x3c4
  45. #define MAP_MASK           2
  46.  
  47. typedef enum {RAM, XMS, EMS, DSK, GIF, END} storage_type;
  48.  
  49. struct IMAGE {
  50.     storage_type type;
  51.     UINT start;
  52.     UINT block_size;
  53.     UINT time;
  54.     UINT sound;
  55.  
  56.     union {
  57.         char        *ptr;
  58.         int          handle;
  59.         long int    offset;
  60.     } d;
  61. } *image = NULL;
  62.  
  63. PALETTE palette;
  64. int colours;
  65.  
  66. int XMS_avail, EMS_avail;
  67. int DSK_initialised     = FALSE;
  68. char *input_file        = NULL;
  69. int    text_out            = TRUE;
  70. int    sound_enabled    = TRUE;
  71. char  buffer_type        = 'N';
  72.  
  73. FILE *DSK_buffer;
  74.  
  75. FILE *GIF_file;
  76. FILE *ANM_file;
  77. int num_images;
  78.  
  79. void exit_free(int code)
  80. {
  81.     int i;
  82.  
  83.     for (i =  1; i < num_images; i++)   /* Image[0] points to same buffers as image[1] */
  84.         switch(image[i].type) {
  85.         case XMS:    XMMfree(image[i].d.handle);    break;
  86.         case EMS:    EMMfree(image[i].d.handle);    break;
  87.         case RAM:    farfree(image[i].d.ptr);        break;
  88.         }
  89.  
  90.     farfree(image);
  91.     if (DSK_initialised) {
  92.         fclose(DSK_buffer);
  93.         unlink("ANIM.TMP");
  94.     }
  95.     DGifCloseFile();
  96.     exit(code);
  97. }
  98.  
  99. void display_memory_status(void)
  100. {
  101.     printf("RAM: %lu Kbytes free\n", (farcoreleft() - 16384L)/1024);
  102.     if (XMS_avail)        printf("XMS: %lu Kbytes free\n",  XMMcoreleft()/1024);
  103.     else                    printf("XMS is not available\n");
  104.     if (EMS_avail)        printf("EMS: %lu Kbytes free\n",  EMMcoreleft()/1024);
  105.     else                    printf("EMS is not available\n");
  106.     printf("Press any key to continue: "); getch();
  107.     printf("\n");
  108. }
  109.  
  110. void do_animation(void)
  111. {
  112.     int n, i, vis_page, plane;
  113.     char *base, *pagea, *pageb;
  114.     struct IMAGE *img;
  115.  
  116.     pageb = setact_200(1);
  117.     pagea = setact_200(0);
  118.     vis_page = 0;
  119.     setvis_200(0);
  120.     while (!kbhit()) {
  121.         for (n = 0, img = image; n < num_images; n++, img++) {
  122.             if (img->type == GIF) {
  123.                 fseek(GIF_file, img->d.offset, SEEK_SET);
  124.                 DGifSetupDecompress(img->block_size*4);
  125.             } else if (img->type == DSK)
  126.                 fseek(DSK_buffer, img->d.offset, SEEK_SET);
  127.             for (plane = 0; plane < 4; plane++) {
  128.                 base = pageb + img->start;
  129.                 outport(SC_INDEX, (0x0100 << plane) | MAP_MASK);    /* Write to only 1 plane */
  130.                 switch(img->type) {
  131.                 case RAM:
  132.                     memcpy(base, img->d.ptr + img->block_size*plane, img->block_size);
  133.                     break;
  134.                 case XMS:
  135.                     XMMcopyfrom(img->block_size, img->d.handle, img->block_size*plane, base);
  136.                     break;
  137.                 case EMS:
  138.                     EMMcopyfrom(img->block_size, img->d.handle, img->block_size*plane, base);
  139.                     break;
  140.                 case DSK:
  141.                     fread(base, 1, img->block_size, DSK_buffer);
  142.                     break;
  143.                 case GIF:
  144.                     for (i = 0; i < img->block_size; i += 80, base += 80)
  145.                         DGifGetLine(base, 80);
  146.                     break;
  147.                 }
  148.             }
  149.  
  150.             WaitForVerticalRetrace();
  151.             vis_page = !vis_page;
  152.             setvis_200(vis_page);
  153.  
  154.             if (sound_enabled)
  155.                 if (img->sound)            sound(img->sound);
  156.                 else                            nosound();
  157.             delay(img->time);
  158.  
  159.             base = pagea; pagea = pageb; pageb = base;
  160.         }
  161.     }
  162.     getch();
  163.    nosound();
  164.     end320x200mode();
  165. }
  166.  
  167. void open_GIF(char *fname)
  168. {
  169.     char filename[256];
  170.     int ColorRes, BackGround, BitsPerPixel, maxcol, maxrow;
  171.  
  172.     sprintf(filename, "%s.gif", fname);
  173.     if ((GIF_file = DGifOpenFile(filename)) == NULL) {
  174.         printf("Couldn't load %s\n", filename);
  175.         exit(3);
  176.     }
  177.  
  178.     printf("Opening %s\n", filename);
  179.     DGifGetScreenDesc(&maxcol, &maxrow, &ColorRes, &BackGround, &BitsPerPixel, (char *) palette);
  180.  
  181.     if (maxcol != 80 || maxrow != 800) {
  182.         printf( "Invalid image size -- must be 80*800, but is %d*%d.\n", maxcol, maxrow);
  183.         exit(1);
  184.     }
  185.     colours = 1 << BitsPerPixel;
  186. }
  187.  
  188. void open_ANM(char *fname)
  189. {
  190.     char filename[256];
  191.  
  192.     sprintf(filename, "%s.ANM", fname);
  193.     if ((ANM_file = fopen(filename, "rt")) == NULL) {
  194.         printf("Couldn't load %s\n", filename);
  195.         exit(3);
  196.     }
  197.  
  198.     printf("Opening %s\n", filename);
  199.     fscanf(ANM_file, "%*[^\n]\n");    /* Skip first line */
  200. }
  201.  
  202. void move_to_RAM(void *dest, void *source, UINT size, UINT plane)
  203. {
  204.     memcpy(*(char **)dest + size*plane, source, size);
  205. }
  206.  
  207. void move_to_XMS(void *dest, void *source, UINT size, UINT plane)
  208. {
  209.     XMMcopyto(size, source, *(int *)dest, (long)size*plane);
  210. }
  211.  
  212. void move_to_EMS(void *dest, void *source, UINT size, UINT plane)
  213. {
  214.     EMMcopyto(size, source, *(int *)dest, (long)size*plane);
  215. }
  216. void move_to_DSK(void *dest, void *source, UINT size, UINT plane)
  217. {
  218.     fwrite(source, 1, size, DSK_buffer);
  219. #pragma warn -par
  220. }
  221. #pragma warn .par
  222.  
  223. void move_to_GIF(void *dest, void *source, UINT size, UINT plane)
  224. {
  225. #pragma warn -par
  226. }
  227. #pragma warn .par
  228.  
  229. int load_image(int n)
  230. {
  231.     int plane, i;
  232.     char *dest_name[] = { "RAM", "XMS", "EMS", "DSK", "GIF"};
  233.     UINT Left, Width, Height, Row;
  234.     unsigned long image_size;
  235.     GifRecordType RecordType;
  236.     char far *base;
  237.     char *buffer;
  238.     storage_type destination;
  239.     static void (*move_to_frame[])(void *dest, void *source, UINT size, UINT plane) = {
  240.         move_to_RAM, move_to_XMS, move_to_EMS, move_to_DSK, move_to_GIF, NULL};
  241.  
  242.     static UINT min_time[] = { 8, 5, 5, 5, 0 }; /* Minimum delay to avoid screen artifacts */
  243.  
  244.     if (kbhit()) if (getch() == 0x1b)             return FALSE;
  245.  
  246.     DGifGetRecordType(&RecordType);
  247.     if (RecordType != IMAGE_DESC_RECORD_TYPE) return FALSE;
  248.  
  249.     DGifGetImageDesc(&Left, &Row, &Width, &Height, NULL);
  250.     image_size = Height * Width;
  251.  
  252.     switch (buffer_type) {
  253.     case 'G':    destination = GIF; break;
  254.     case 'D':    destination = DSK; break;
  255.     case 'N':    destination = END; break;
  256.     }
  257.     if (EMS_avail)
  258.         if (EMMcoreleft() > image_size)             destination = EMS;
  259.     if (XMS_avail)
  260.         if (XMMcoreleft() > image_size)             destination = XMS;
  261.     if (farcoreleft() > image_size + 80000L)     destination = RAM;
  262.  
  263.     fscanf(ANM_file, " %d, %d, %*[^\n]\n", &image[n].time, &image[n].sound);
  264.  
  265.     image[n].start = Row * Width;
  266.     image[n].time = max(min_time[destination], image[n].time);
  267.     image[n].block_size = (UINT) (image_size/4);
  268.  
  269.     if (destination == END)            return FALSE;
  270.     if (destination == DSK) {
  271.         if (!DSK_initialised) {
  272.             if ((DSK_buffer = fopen("ANIM.TMP", "wb")) == NULL) {
  273.                 if (!text_out) end320x200mode();
  274.                 printf("Error in Disk initialisation.\n");
  275.                 return FALSE;
  276.             }
  277.             DSK_initialised = TRUE;
  278.         }
  279.     }
  280.  
  281.     image[n].type = destination;
  282.     if (text_out)
  283.         printf("Loading frame %3d (%3d..%3d x %d) to %s\n", n,
  284.                             Row, Row+Height/4 - 1, Width*4, dest_name[destination]);
  285.  
  286.     buffer = farmalloc(image[n].block_size);
  287.     if (buffer == NULL) {
  288.         if (!text_out) end320x200mode();
  289.         printf("Error allocating buffer.\n");
  290.         return FALSE;
  291.     }
  292.  
  293.     switch (destination) {
  294.     case RAM:
  295.         image[n].d.ptr = farmalloc(image_size);
  296.         if (image[n].d.ptr == NULL) {
  297.             if (!text_out) end320x200mode();
  298.             printf("Error allocating RAM.\n");
  299.             exit_free(3);
  300.         }
  301.         break;
  302.  
  303.     case XMS:
  304.         image[n].d.handle = XMMalloc(image_size);    /* Allocate EMB.  */
  305.         if (image[n].d.handle == XMMOOPS) {
  306.             if (!text_out) end320x200mode();
  307.             printf("Error %x allocating EMB.\n", (int) _XMMerror);
  308.             exit_free(3);
  309.         }
  310.         break;
  311.  
  312.     case EMS:
  313.         image[n].d.handle = EMMalloc(image_size);    /* Allocate EMS.  */
  314.         if (image[n].d.handle == EMMOOPS) {
  315.             if (!text_out) end320x200mode();
  316.             printf("Error %x allocating EMS.\n", (int) _EMMerror);
  317.             exit_free(3);
  318.         }
  319.         break;
  320.  
  321.     case DSK:
  322.         image[n].d.offset = ftell(DSK_buffer);
  323.         break;
  324.  
  325.     case GIF:
  326.         image[n].d.offset = ftell(GIF_file) - 1;
  327.         break;
  328.     }
  329.  
  330.     /* Scan the content of the GIF file and load the image in */
  331.     for (plane = 0; plane < 4; plane++) {
  332.         base = buffer;
  333.         for (i = 0; i < Height/4; i++, base += Width)
  334.             DGifGetLine(base, Width);
  335.  
  336.         if (!text_out) {
  337.             outport(SC_INDEX, ((0x0F00 << plane) & 0xF00) | MAP_MASK);
  338.             memcpy(MK_FP(0xa000, image[n].start), buffer, image[n].block_size);
  339.         }
  340.  
  341.         move_to_frame[image[n].type](&image[n].d, buffer, image[n].block_size, plane);
  342.     }
  343.     farfree(buffer);
  344.     return TRUE;
  345. }
  346.  
  347. void usage(char *prog_name)
  348. {
  349.     printf("Command syntax: %s [/T{0|1}][/S{0|1}][/B{D|G|N}] file\n\n", prog_name);
  350.     printf("/T1 = text output, listing image numbers as they are loaded\n");
  351.     printf("/T0 = graphic output, displaying images as they are loaded\n");
  352.     printf("      default is /T%d\n\n", text_out);
  353.     printf("/S1 = sound enabled\n");
  354.     printf("/S0 = sound disabled\n");
  355.     printf("      default is /S%d\n\n", sound_enabled);
  356.     printf("/BD = use disk as buffer when RAM is full\n");
  357.     printf("/BG = use GIF as buffer (expand during animation) when RAM is full\n");
  358.     printf("/BN = use no buffer when RAM is full\n");
  359.     printf("      default is /B%c\n\n", buffer_type);
  360.     exit(0);
  361. }
  362. /********************************************************************
  363.  Process command line arguments. */
  364.  
  365. void get_args(int argc, char *argv[])
  366. {
  367.     int i;
  368.  
  369.     if (argc == 1)         usage(argv[0]);
  370.     for (i = 1; i < argc; i++) {
  371.         if (argv[i][0] != '/' && argv[i][0] != '-') {
  372.             if (input_file != NULL) {
  373.                 printf("Can only display 1 file at a time.\n\n");
  374.                 usage(argv[0]);
  375.             }
  376.             input_file = argv[i];
  377.             continue;
  378.         }
  379.         if (argv[i][1] == '?')         usage(argv[0]);
  380.  
  381.         switch(toupper(argv[i][1])) {
  382.         case 'T': text_out        = atoi(&argv[i][2]);     break;
  383.         case 'S': sound_enabled    = atoi(&argv[i][2]);     break;
  384.         case 'B': buffer_type      = toupper(argv[i][2]);    break;
  385.         default:
  386.             printf("Invalid command line switch: %s\n(Must be /B, /S, or /T)\n\n", argv[i]);
  387.             usage(argv[0]);
  388.         }
  389.     }
  390.     if (input_file == NULL) {
  391.         printf("No files to process.\n");
  392.         usage(argv[0]);
  393.     }
  394. }
  395.  
  396. void cdecl main(int argc, char *argv[])
  397. {
  398.     printf("ANIM v1.50 -- GIF animation viewer.\n");
  399.     printf("By F van der Hulst. Copyright 1992\n\n");
  400.     get_args(argc, argv);
  401.  
  402.     image = calloc(MAX_IMAGES, sizeof(struct IMAGE));
  403.     XMS_avail = !XMMlibinit();    /* INITIALIZE XMSLIB! VERY IMPORTANT! */
  404.     EMS_avail = !EMMlibinit();    /* INITIALIZE EMSLIB! VERY IMPORTANT! */
  405.  
  406.     display_memory_status();
  407.     open_ANM(input_file);
  408.     open_GIF(input_file);
  409.     if (!text_out) {
  410.         set320x200x4mode();
  411.         setvgapalette(&palette, colours);
  412.     }
  413.     for (num_images = 1; num_images < MAX_IMAGES; num_images++)
  414.         if (!load_image(num_images)) break;
  415.     image[0] = image[1];
  416.     fclose(ANM_file);
  417.  
  418.     if (num_images > 2) {
  419.         if (DSK_initialised) {
  420.             fclose(DSK_buffer);
  421.             DSK_buffer = fopen("ANIM.TMP", "rb");
  422.         }
  423.         if (text_out) {
  424.             set320x200x4mode();
  425.             setvgapalette(&palette, colours);
  426.         }
  427.         do_animation();
  428.         end320x200mode();
  429.     }
  430.     exit_free(0);
  431. }
  432.