/*****************************************************************************
*   "Gif-Lib" - Yet another gif library.				     *
*									     *
* Written by:  Gershon Elber			IBM PC Ver 0.1,	Jun. 1989    *
******************************************************************************
* Module to dump graphic devices into a GIF file. Current supported devices: *
* 1. Hercules.								     *
******************************************************************************
* History:								     *
* 22 Jun 89 - Version 1.0 by Gershon Elber.				     *
*****************************************************************************/

#include <dos.h>
#include <alloc.h>
#include <stdio.h>
#include <graphics.h>
#include "gif_lib.h"

#define PROGRAM_NAME	"GIF_LIBRARY"
#define VERSION		"á Version 1.0, "

static int GraphDriver = HERCMONO,			/* Device parameters */
	   GraphMode = HERCMONOHI,
	   ScreenXMax = 720,
	   ScreenYMax = 348,
	   ScreenColorBits = 1;
static unsigned int ScreenBase;

static char *VersionStr =
	PROGRAM_NAME
	"	IBMPC "
	VERSION
	"	Gershon Elber,	"
	__DATE__ ",   " __TIME__ "\n"
	"(C) Copyright 1989 Gershon Elber, Non commercial use only.\n";

static void GetScanLine(PixelType *ScanLine, int Y);
static int HandleGifError(GifFileType *GifFile);

/******************************************************************************
* Dump the given Device, into given File as GIF format:			      *
* Return 0 on success, -1 if device not supported, or GIF-LIB error number.   *
* See graphics.h for exact definition of GraphDriver/Mode.		      *
******************************************************************************/
int DumpScreen(char *FileName, int ReqGraphDriver, int ReqGraphMode)
{
    int i;
    static PixelType *ScanLine;
    static GifColorType HerculesColorMap[2] = { { 0, 0, 0 },
						{ 255, 255, 255 } };
    GifFileType *GifFile;

    switch (ReqGraphDriver) {		  /* return on non supported screens */
	case HERCMONO:
	    ScreenXMax = 720;
	    ScreenYMax = 350;
	    ScreenColorBits = 1;
	    ScreenBase = 0xb000;
	    break;
	default:
	    return -1;
    }

    ScanLine = (PixelType *) malloc(sizeof(PixelType) * ScreenXMax);

    GraphDriver = ReqGraphDriver;
    GraphMode = ReqGraphMode;

    if ((GifFile = EGifOpenFileName(FileName, FALSE)) == NULL) {
	free((char *) ScanLine);
	return HandleGifError(GifFile);
    }

    if (EGifPutScreenDesc(GifFile, ScreenXMax, ScreenYMax, ScreenColorBits,
			  0, ScreenColorBits, HerculesColorMap) == ERROR) {
	free((char *) ScanLine);
	return HandleGifError(GifFile);
    }

    if (EGifPutImageDesc(GifFile, 0, 0, ScreenXMax, ScreenYMax, FALSE, 1,
			 NULL) == ERROR) {
	free((char *) ScanLine);
	return HandleGifError(GifFile);
    }

    for (i=0; i<ScreenYMax; i++) {
	GetScanLine(ScanLine, i);
	if (EGifPutLine(GifFile, ScanLine, ScreenXMax) == ERROR) {
	    free((char *) ScanLine);
	    return HandleGifError(GifFile);
	}
    }

    if (EGifCloseFile(GifFile) == ERROR) {
	free((char *) ScanLine);
	return HandleGifError(GifFile);
    }

    free((char *) ScanLine);
    return 0;
}

/******************************************************************************
* Update the given scan line buffer with the pixel levels of the Y line.      *
* This routine is device specific, so make sure you know was you are doing    *
******************************************************************************/
static void GetScanLine(PixelType *ScanLine, int Y)
{
    unsigned char ScreenByte;
    int i, j, k;
    unsigned int Offset, Bit;

    switch (GraphDriver) {
	case HERCMONO:
	    Offset = 0x2000 * (Y % 4) + (Y / 4) * (ScreenXMax / 8);
	    /* In one scan lines we have ScreenXMax / 8 bytes: */
	    for (i=0, k=0; i<ScreenXMax / 8; i++) {
		ScreenByte = (unsigned char) peekb(ScreenBase, Offset++);
		for (j=0, Bit = 0x80; j<8; j++) {
		    ScanLine[k++] = (ScreenByte & Bit ? 1 : 0);
		    Bit >>= 1;
		}
	    }
	    break;
	default:
	    break;
    }
}

/******************************************************************************
* Handle last GIF error. Try to close the file and free all allocated memory. *
******************************************************************************/
static int HandleGifError(GifFileType *GifFile)
{
    int i = GifLastError();

    if (EGifCloseFile(GifFile) == ERROR) {
	GifLastError();
    }
    return i;
}
