home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD2.mdf / c / library / dos / grafik / sega / pvquant / anim / anim.c next >
Encoding:
C/C++ Source or Header  |  1991-11-29  |  9.8 KB  |  395 lines

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