From: hgm@ncsu.edu (Hal G. Meeks)
Subject: Re: .DL anim viewer?
Organization: North Carolina State University
Date: Tue, 25 Aug 1992 23:07:30 GMT

ged@phantom.cs.hut.fi (Camillo S{rs) writes:

>In <1992Aug25.052621.24860@uwm.edu> jdblake@csd4.csd.uwm.edu (John David Blake) writes:

>>Does anyone out there know of an FTP site where I could get a .DL anim
>>format viewer? (For Amiga, of course)

This is what I've been doing: 

1. Use the DL2GL converter to get a gl file that I can work with. 
2. Splitting up the resulting GL file with glsplit, a neat utility that comes with one of the GL
   viewers for the amiga (the one written by John Bickers). 
3. Using HamLabPlus to convert the resulting files into HAM iff images. 
4. Recompress the iff files into an anim format file with Crygenic software's BuildAnim. 

Seems like a lot of work.....but the the results look a lot better than any of the gl viewers
I've seen for the amiga. Since HamLabPlus has an Arexx port, at some point I'll get annoyed with
having to do all of this by hand, and will write a little program to do it for me. 

--hal

------------------cut here-------------------
/*
 * dltogl.c -- convert .DL animations into .GL animations.
 *
 * usage: dltogl file.dl [file.gl]
 *
 * If no .gl file is specified, the images and control file will be
 * written to separate files.  The control file will always be "dl.txt",
 * the images "clpN.clp" and a palette file called "palette.pic".
 *
 * Author:
 *	George Phillips
 *	<phillips@cs.ubc.ca>
 */

#include <stdio.h>
#ifdef __TURBOC__
#include <alloc.h>
#else
extern char* malloc();
#endif

#define FOW	"wb"

FILE*	gl;
int		gl_fileno;

FILE* file_open();
int file_close();

#define isneg16(x)	((x) & 0x8000)
#define neg16(x)	((~(x) + 1) & 0x7fff)

main(argc, argv)
int		argc;
char*	argv[];
{
	unsigned int i, j;
	FILE* fp;
	int num_scrn;
	int ctl_len;
	int ch;
	int format;
	static char title[21];
	static char author[21];
	static unsigned char pal[256*3];
	unsigned char* screen;
	static unsigned char halfscreen[160*100];
	static char fname[32];
	int picnum;
	int images_per_screen;
	FILE* ctl;
	int fx, fy;
	int* cmd;
	int labelpos;
	int cmdnum;

	if (argc != 2 && argc != 3)
		die("usage: gltodl file.dl [file.gl]");

	if (!(fp = fopen(argv[1], "rb"))) {
		fprintf(stderr, "gltodl: can't open %s\n", argv[1]);
		exit(1);
	}

	gl = 0;
	gl_fileno = 0;
	if (argc == 3 && !(gl = fopen(argv[2], FOW))) {
		fprintf(stderr, "gltodl: can't open %s for writing\n", argv[2]);
		exit(1);
	}

	if (fgetc(fp) != 2)
		die("gltodl: only version 2 files can be handled");

	switch (format = fgetc(fp)) {
	case 0:
		fx = fy = 0;
		images_per_screen = 1;
		break;
	case 1:
		fx = 80;
		fy = 50;
		images_per_screen = 4;
		break;
	default:
		die("gltodl: only large and medium formats are handled");
		break;
	}

	title[20] = author[20] = 0;
	for (i = 0; i < 20; i++)
		title[i] = fgetc(fp) ^ 255;

	for (i = 0; i < 20; i++)
		author[i] = fgetc(fp) ^ 255;

	for (i = 0; i < 20; i++) {
		if ((unsigned char)title[i] == 255) title[i] = 0;
		if ((unsigned char)author[i] == 255) author[i] = 0;
	}

	num_scrn = fgetc(fp);
	ctl_len = fgetc(fp);

	if (!(cmd = (int*)malloc(ctl_len * sizeof(int))))
		die("dltogl: out of memory");

	gl_numfiles(num_scrn * images_per_screen + 1 + 1);

	/* mebbe this is the border colour? */
	for (i = 0; i < 3; i++)
		fgetc(fp);

	for (i = 0; i < 256; i++) {
		pal[i*3] = fgetc(fp);
		pal[i*3+1] = fgetc(fp);
		pal[i*3+2] = fgetc(fp);
	}

	if (!(screen = malloc(320 * 200)))
		die("dltogl: not enough memory.");

	memset(screen, 0, 320 * 200);
	writepic(screen, 320, 200, "palette.pic", pal);

	picnum = 0;
	for (j = 0; j < num_scrn; j++) {
		fread(screen, 320 * 200, 1, fp);
		switch (format) {
		case 0: /* large */
			sprintf(fname, "clp%d.clp", picnum++);
			writepic(screen, 320, 200, fname, (unsigned char*)0);
			break;
		case 1: /* medium */
			for (i = 0; i < 4; i++) {
				unsigned char*	src;
				unsigned char*	dst;
				int				row;
				int				col;

				sprintf(fname, "clp%d.clp", picnum++);
				src = screen + (i % 2) * 160 + (i / 2) * 100 * 320;
				dst = halfscreen;
				for (row = 0; row < 100; row++) {
					for (col = 0; col < 160; col++)
						*dst++ = *src++;
					src += 160;
				}
				writepic(halfscreen, 160, 100, fname, (unsigned char*)0);
			}
		}
	}

	ctl = file_open("dl.txt", FOW);

	fprintf(ctl, "; This GL file was converted from DL format by dltogl\r\n");
	fprintf(ctl, "; Title:  %s\r\n", title);
	fprintf(ctl, "; Author: %s\r\n", author);
	/* could print all the other keeno information */

	fprintf(ctl, "video l\r\n");
	fprintf(ctl, "pload palette,1\r\n");
	fprintf(ctl, "palette 1\r\n");
	fprintf(ctl, "pfree 1\r\n");
	for (i = 0; i < num_scrn * images_per_screen; i++)
		fprintf(ctl, "cload clp%d,%d\r\n", i, i + 1);

	for (i = 0; i < ctl_len; i++) {
		j = fgetc(fp);
		j += fgetc(fp) << 8;
		cmd[i] = j;
	}

	labelpos = 0;
	if (isneg16(cmd[ctl_len - 1])) {
		labelpos = neg16(cmd[ctl_len - 1]) + 1;
		ctl_len--;	/* ignore that last command */
	}

	for (i = 0, cmdnum = 0; i < ctl_len; i++, cmdnum++) {
		if (cmdnum == labelpos)
			fprintf(ctl, "forever:\r\n");
		if (isneg16(cmd[i])) {
			i++;
			fprintf(ctl, "waitkey %d\r\n", cmd[i]);
		}
		else
			fprintf(ctl, "putup %d,%d,%d,10\r\n", fx, fy, cmd[i] + 1);
	}
	fprintf(ctl, "goto forever\r\n");
	fputc(26, ctl);
	file_close(ctl);

	fclose(fp);

	if (gl)
		fclose(gl);

	exit(0);
}

die(s)char*s;{fprintf(stderr,"%s\n",s);exit(1);}

#define BLOCKSIZE	(8192)

writepic(pixel, width, height, filename, cmap)
unsigned char* pixel;
int	width;
int	height;
char* filename;
unsigned char* cmap;
{
	FILE*	fp;
	unsigned int i;
	static unsigned char buf[BLOCKSIZE];
	unsigned char* p;
	int row, col;

	fp = file_open(filename, FOW);

	/* write header */
	writeshort(fp, 0x1234);	/* magic number */
	writeshort(fp, width);
	writeshort(fp, height);
	writeshort(fp, 0);
	writeshort(fp, 0);
	fputc(8, fp);						/* bits per pixel */
	fputc(0xff, fp);					/* byte here is always 255 */
	fputc('L', fp);						/* video mode */
	if (cmap) {
		writeshort(fp, 4);		/* extra information descriptor */
		writeshort(fp, 768);	/* extra information length */
		fwrite(cmap, 768, 1, fp);
	}
	else {
		writeshort(fp, 0);
		writeshort(fp, 0);
	}

	/* number of packed blocks in file */
	writeshort(fp, ((long)width * height + BLOCKSIZE - 1) / BLOCKSIZE);

	i = 0;
	for (row = height - 1; row >= 0; row--) {
		p = pixel + row * width;
		for (col = 0; col < width; col++) {
			buf[i++] = *p++;
			if (i == BLOCKSIZE) {
				outpackblock(fp, buf, i);
				i = 0;
			}
		}
	}
	if (i > 0)
		outpackblock(fp, buf, i);

	file_close(fp);
}

outpackblock(fp, buf, len)
FILE*	fp;
char*	buf;
int	len;
{
	static char	packbuf[BLOCKSIZE * 4 - 1];	/* overkill */
	int	packlen;

	packlen = packblock(buf, packbuf, len);
	fwrite(packbuf, packlen, 1, fp);
}

packblock(src, dest, len)
char*	src;
char*	dest;
int		len;
{
	unsigned char*	s;
	unsigned char*	r;
	unsigned char*	d;
	static int	overhead[256];
	int	i;
	int	esc;
	int	escpresent;
	int	minover;
	int	packlen;

	for (i = 0; i < 256; i++)
		overhead[i] = 0;

	/* do first pass to find optimal esc byte */
	for (s = src; s < src + len; s = r) {
		for (r = s; *r == *s && r < src + len; r++)
			;
		if (r - s < 4)
			overhead[*s]++;
	}

	minover = len + 1;
	for (i = 0; i < 256; i++) {
		if (overhead[i] < minover) {
			minover = overhead[i];
			esc = i;
		}
	}
	escpresent = overhead[esc] == 0;

	/* now run-length encode on the second pass */

	d = dest + 5;
	for (s = src; s < src + len; s = r) {
		for (r = s; *r == *s && r < src + len; r++)
			;
		if (r - s < 4 && (!escpresent || *s != esc)) {
			while (s < r)
				*d++ = *s++;
		}
		else {
			if (r - s > 255) {
				*d++ = esc;
				*d++ = 0;
				*d++ = (r - s) & 0xff;
				*d++ = ((r - s) >> 8) & 0xff;
				*d++ = *s++;
			}
			else {
				*d++ = esc;
				*d++ = r - s;
				*d++ = *s++;
			}
		}
	}

	packlen = d - dest;

	/* fill in the block header */

	*dest++ = packlen & 0xff;			/* packed block size */
	*dest++ = ((packlen) >> 8) & 0xff;
	*dest++ = len & 0xff;
	*dest++ = (len >> 8) & 0xff;		/* unpacked block size */
	*dest++ = esc;						/* escape byte */

	return packlen;
}

writeshort(fp, s)
FILE*	fp;
int		s;
{
	fputc(s & 255, fp);
	fputc((s >> 8) & 255, fp);
}

writelong(fp, l)
FILE*	fp;
long	l;
{
	fputc(l & 255, fp);
	fputc((l >> 8) & 255, fp);
	fputc((l >> 16) & 255, fp);
	fputc((l >> 24) & 255, fp);
}

long gl_eof;
long gl_filestart;

gl_numfiles(n)
int	n;
{
	if (gl) {
		fseek(gl, 0, 0);
		writeshort(gl, n * 17);
		gl_eof = 2 + n * 17;
	}
}

FILE* file_open(name, mode)
char*	name;
char*	mode;
{
	FILE*	fp;
	char	fname[14];

	if (!gl) {
		if (!(fp = fopen(name, mode))) {
			fprintf(stderr, "dltogl: can't open %s\n", name);
			exit(1);
		}
		return fp;
	}

	fseek(gl, 2 + gl_fileno++ * 17, 0);
	writelong(gl, gl_eof);
	memset(fname, 0, 13);
	strcpy(fname, name);
	fwrite(fname, 13, 1, gl);
	fseek(gl, gl_filestart = gl_eof + 4, 0);
	return gl;
}

int file_close(fp)
FILE*	fp;
{
	if (!gl)
		return fclose(fp);

	gl_eof = ftell(gl);
	fseek(gl, gl_filestart - 4, 0);
	writelong(gl, gl_eof - gl_filestart);
}
--
hgm@ccvr1.cc.ncsu.edu	"The trick is -- find a name for it.
                         Then you can sell it. End of the Revolution."