home *** CD-ROM | disk | FTP | other *** search
- /************************************************************************
- * *
- * Copyright (c) 1992, Frank van der Hulst *
- * All Rights Reserved *
- * *
- ************************************************************************
- * *
- * Authors: *
- * FvdH - Frank van der Hulst (Wellington, NZ) *
- * *
- * Versions: *
- * V1.0 911031 FvdH - Released as part of PVQUAN13.ZIP *
- * V1.4 920306 FvdH - Improved usage information (PVQUAN14.ZIP) *
- * *
- ************************************************************************/
-
- /*
- This program produces animation on a 320*200 screen using page flipping.
- The first command line parameter must be a standard 2D file containing the
- first image. The following files are produced by DIFF, and contain
- information about the differences between alternate images.
- */
-
- #include <stdlib.h>
- #include <stdio.h>
- #include <conio.h>
- #include <dos.h>
- #include <alloc.h>
- #include <string.h>
- #include <ctype.h>
-
- #define FALSE 0
- #define TRUE 1
-
- #define UINT unsigned int
-
- #include "xmslib.h"
- #include "emslib.h"
- #include "gif_lib.h"
- #include "vga.h"
-
- #define MAX_IMAGES 50
-
- #define SC_INDEX 0x3c4
- #define MAP_MASK 2
-
- typedef enum {RAM, XMS, EMS, DSK, GIF, END} storage_type;
-
- struct IMAGE {
- storage_type type;
- UINT start;
- UINT block_size;
- UINT time;
- UINT sound;
-
- union {
- char *ptr;
- int handle;
- long int offset;
- } d;
- } *image = NULL;
-
- PALETTE palette;
- int colours;
-
- int XMS_avail, EMS_avail;
- int DSK_initialised = FALSE;
- char *input_file = NULL;
- int text_out = TRUE;
- int sound_enabled = TRUE;
- char buffer_type = 'N';
-
- FILE *DSK_buffer;
-
- FILE *GIF_file;
- FILE *ANM_file;
- int num_images;
-
- void exit_free(int code)
- {
- int i;
-
- for (i = 1; i < num_images; i++) /* Image[0] points to same buffers as image[1] */
- switch(image[i].type) {
- case XMS: XMMfree(image[i].d.handle); break;
- case EMS: EMMfree(image[i].d.handle); break;
- case RAM: farfree(image[i].d.ptr); break;
- }
-
- farfree(image);
- if (DSK_initialised) {
- fclose(DSK_buffer);
- unlink("ANIM.TMP");
- }
- DGifCloseFile();
- exit(code);
- }
-
- void display_memory_status(void)
- {
- printf("RAM: %lu Kbytes free\n", (farcoreleft() - 16384L)/1024);
- if (XMS_avail) printf("XMS: %lu Kbytes free\n", XMMcoreleft()/1024);
- else printf("XMS is not available\n");
- if (EMS_avail) printf("EMS: %lu Kbytes free\n", EMMcoreleft()/1024);
- else printf("EMS is not available\n");
- printf("Press any key to continue: "); getch();
- printf("\n");
- }
-
- void do_animation(void)
- {
- int n, i, vis_page, plane;
- char *base, *pagea, *pageb;
- struct IMAGE *img;
-
- pageb = setact_200(1);
- pagea = setact_200(0);
- vis_page = 0;
- setvis_200(0);
- while (!kbhit()) {
- for (n = 0, img = image; n < num_images; n++, img++) {
- if (img->type == GIF) {
- fseek(GIF_file, img->d.offset, SEEK_SET);
- DGifSetupDecompress(img->block_size*4);
- } else if (img->type == DSK)
- fseek(DSK_buffer, img->d.offset, SEEK_SET);
- for (plane = 0; plane < 4; plane++) {
- base = pageb + img->start;
- outport(SC_INDEX, (0x0100 << plane) | MAP_MASK); /* Write to only 1 plane */
- switch(img->type) {
- case RAM:
- memcpy(base, img->d.ptr + img->block_size*plane, img->block_size);
- break;
- case XMS:
- XMMcopyfrom(img->block_size, img->d.handle, img->block_size*plane, base);
- break;
- case EMS:
- EMMcopyfrom(img->block_size, img->d.handle, img->block_size*plane, base);
- break;
- case DSK:
- fread(base, 1, img->block_size, DSK_buffer);
- break;
- case GIF:
- for (i = 0; i < img->block_size; i += 80, base += 80)
- DGifGetLine(base, 80);
- break;
- }
- }
-
- WaitForVerticalRetrace();
- vis_page = !vis_page;
- setvis_200(vis_page);
-
- if (sound_enabled)
- if (img->sound) sound(img->sound);
- else nosound();
- delay(img->time);
-
- base = pagea; pagea = pageb; pageb = base;
- }
- }
- getch();
- nosound();
- end320x200mode();
- }
-
- void open_GIF(char *fname)
- {
- char filename[256];
- int ColorRes, BackGround, BitsPerPixel, maxcol, maxrow;
-
- sprintf(filename, "%s.gif", fname);
- if ((GIF_file = DGifOpenFile(filename)) == NULL) {
- printf("Couldn't load %s\n", filename);
- exit(3);
- }
-
- printf("Opening %s\n", filename);
- DGifGetScreenDesc(&maxcol, &maxrow, &ColorRes, &BackGround, &BitsPerPixel, (char *) palette);
-
- if (maxcol != 80 || maxrow != 800) {
- printf( "Invalid image size -- must be 80*800, but is %d*%d.\n", maxcol, maxrow);
- exit(1);
- }
- colours = 1 << BitsPerPixel;
- }
-
- void open_ANM(char *fname)
- {
- char filename[256];
-
- sprintf(filename, "%s.ANM", fname);
- if ((ANM_file = fopen(filename, "rt")) == NULL) {
- printf("Couldn't load %s\n", filename);
- exit(3);
- }
-
- printf("Opening %s\n", filename);
- fscanf(ANM_file, "%*[^\n]\n"); /* Skip first line */
- }
-
- void move_to_RAM(void *dest, void *source, UINT size, UINT plane)
- {
- memcpy(*(char **)dest + size*plane, source, size);
- }
-
- void move_to_XMS(void *dest, void *source, UINT size, UINT plane)
- {
- XMMcopyto(size, source, *(int *)dest, (long)size*plane);
- }
-
- void move_to_EMS(void *dest, void *source, UINT size, UINT plane)
- {
- EMMcopyto(size, source, *(int *)dest, (long)size*plane);
- }
- void move_to_DSK(void *dest, void *source, UINT size, UINT plane)
- {
- fwrite(source, 1, size, DSK_buffer);
- #pragma warn -par
- }
- #pragma warn .par
-
- void move_to_GIF(void *dest, void *source, UINT size, UINT plane)
- {
- #pragma warn -par
- }
- #pragma warn .par
-
- int load_image(int n)
- {
- int plane, i;
- char *dest_name[] = { "RAM", "XMS", "EMS", "DSK", "GIF"};
- UINT Left, Width, Height, Row;
- unsigned long image_size;
- GifRecordType RecordType;
- char far *base;
- char *buffer;
- storage_type destination;
- static void (*move_to_frame[])(void *dest, void *source, UINT size, UINT plane) = {
- move_to_RAM, move_to_XMS, move_to_EMS, move_to_DSK, move_to_GIF, NULL};
-
- static UINT min_time[] = { 8, 5, 5, 5, 0 }; /* Minimum delay to avoid screen artifacts */
-
- if (kbhit()) if (getch() == 0x1b) return FALSE;
-
- DGifGetRecordType(&RecordType);
- if (RecordType != IMAGE_DESC_RECORD_TYPE) return FALSE;
-
- DGifGetImageDesc(&Left, &Row, &Width, &Height, NULL);
- image_size = Height * Width;
-
- switch (buffer_type) {
- case 'G': destination = GIF; break;
- case 'D': destination = DSK; break;
- case 'N': destination = END; break;
- }
- if (EMS_avail)
- if (EMMcoreleft() > image_size) destination = EMS;
- if (XMS_avail)
- if (XMMcoreleft() > image_size) destination = XMS;
- if (farcoreleft() > image_size + 80000L) destination = RAM;
-
- fscanf(ANM_file, " %d, %d, %*[^\n]\n", &image[n].time, &image[n].sound);
-
- image[n].start = Row * Width;
- image[n].time = max(min_time[destination], image[n].time);
- image[n].block_size = (UINT) (image_size/4);
-
- if (destination == END) return FALSE;
- if (destination == DSK) {
- if (!DSK_initialised) {
- if ((DSK_buffer = fopen("ANIM.TMP", "wb")) == NULL) {
- if (!text_out) end320x200mode();
- printf("Error in Disk initialisation.\n");
- return FALSE;
- }
- DSK_initialised = TRUE;
- }
- }
-
- image[n].type = destination;
- if (text_out)
- printf("Loading frame %3d (%3d..%3d x %d) to %s\n", n,
- Row, Row+Height/4 - 1, Width*4, dest_name[destination]);
-
- buffer = farmalloc(image[n].block_size);
- if (buffer == NULL) {
- if (!text_out) end320x200mode();
- printf("Error allocating buffer.\n");
- return FALSE;
- }
-
- switch (destination) {
- case RAM:
- image[n].d.ptr = farmalloc(image_size);
- if (image[n].d.ptr == NULL) {
- if (!text_out) end320x200mode();
- printf("Error allocating RAM.\n");
- exit_free(3);
- }
- break;
-
- case XMS:
- image[n].d.handle = XMMalloc(image_size); /* Allocate EMB. */
- if (image[n].d.handle == XMMOOPS) {
- if (!text_out) end320x200mode();
- printf("Error %x allocating EMB.\n", (int) _XMMerror);
- exit_free(3);
- }
- break;
-
- case EMS:
- image[n].d.handle = EMMalloc(image_size); /* Allocate EMS. */
- if (image[n].d.handle == EMMOOPS) {
- if (!text_out) end320x200mode();
- printf("Error %x allocating EMS.\n", (int) _EMMerror);
- exit_free(3);
- }
- break;
-
- case DSK:
- image[n].d.offset = ftell(DSK_buffer);
- break;
-
- case GIF:
- image[n].d.offset = ftell(GIF_file) - 1;
- break;
- }
-
- /* Scan the content of the GIF file and load the image in */
- for (plane = 0; plane < 4; plane++) {
- base = buffer;
- for (i = 0; i < Height/4; i++, base += Width)
- DGifGetLine(base, Width);
-
- if (!text_out) {
- outport(SC_INDEX, ((0x0F00 << plane) & 0xF00) | MAP_MASK);
- memcpy(MK_FP(0xa000, image[n].start), buffer, image[n].block_size);
- }
-
- move_to_frame[image[n].type](&image[n].d, buffer, image[n].block_size, plane);
- }
- farfree(buffer);
- return TRUE;
- }
-
- void usage(char *prog_name)
- {
- printf("Command syntax: %s [/T{0|1}][/S{0|1}][/B{D|G|N}] file\n\n", prog_name);
- printf("/T1 = text output, listing image numbers as they are loaded\n");
- printf("/T0 = graphic output, displaying images as they are loaded\n");
- printf(" default is /T%d\n\n", text_out);
- printf("/S1 = sound enabled\n");
- printf("/S0 = sound disabled\n");
- printf(" default is /S%d\n\n", sound_enabled);
- printf("/BD = use disk as buffer when RAM is full\n");
- printf("/BG = use GIF as buffer (expand during animation) when RAM is full\n");
- printf("/BN = use no buffer when RAM is full\n");
- printf(" default is /B%c\n\n", buffer_type);
- exit(0);
- }
- /********************************************************************
- Process command line arguments. */
-
- void get_args(int argc, char *argv[])
- {
- int i;
-
- if (argc == 1) usage(argv[0]);
- for (i = 1; i < argc; i++) {
- if (argv[i][0] != '/' && argv[i][0] != '-') {
- if (input_file != NULL) {
- printf("Can only display 1 file at a time.\n\n");
- usage(argv[0]);
- }
- input_file = argv[i];
- continue;
- }
- if (argv[i][1] == '?') usage(argv[0]);
-
- switch(toupper(argv[i][1])) {
- case 'T': text_out = atoi(&argv[i][2]); break;
- case 'S': sound_enabled = atoi(&argv[i][2]); break;
- case 'B': buffer_type = toupper(argv[i][2]); break;
- default:
- printf("Invalid command line switch: %s\n(Must be /B, /S, or /T)\n\n", argv[i]);
- usage(argv[0]);
- }
- }
- if (input_file == NULL) {
- printf("No files to process.\n");
- usage(argv[0]);
- }
- }
-
- void cdecl main(int argc, char *argv[])
- {
- printf("ANIM v1.50 -- GIF animation viewer.\n");
- printf("By F van der Hulst. Copyright 1992\n\n");
- get_args(argc, argv);
-
- image = calloc(MAX_IMAGES, sizeof(struct IMAGE));
- XMS_avail = !XMMlibinit(); /* INITIALIZE XMSLIB! VERY IMPORTANT! */
- EMS_avail = !EMMlibinit(); /* INITIALIZE EMSLIB! VERY IMPORTANT! */
-
- display_memory_status();
- open_ANM(input_file);
- open_GIF(input_file);
- if (!text_out) {
- set320x200x4mode();
- setvgapalette(&palette, colours);
- }
- for (num_images = 1; num_images < MAX_IMAGES; num_images++)
- if (!load_image(num_images)) break;
- image[0] = image[1];
- fclose(ANM_file);
-
- if (num_images > 2) {
- if (DSK_initialised) {
- fclose(DSK_buffer);
- DSK_buffer = fopen("ANIM.TMP", "rb");
- }
- if (text_out) {
- set320x200x4mode();
- setvgapalette(&palette, colours);
- }
- do_animation();
- end320x200mode();
- }
- exit_free(0);
- }
-