Skip to content

Instantly share code, notes, and snippets.

@Sembiance
Created May 28, 2021 19:33
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Sembiance/b4262c84ee5311ec6ee42f18db64c778 to your computer and use it in GitHub Desktop.
Save Sembiance/b4262c84ee5311ec6ee42f18db64c778 to your computer and use it in GitHub Desktop.
C code that converts a DL file to GL
/*
* 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 <string.h>
#include <stdio.h>
#include <stdlib.h>
#include "dltogl_protos.h"
#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 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: dltogl file.dl [file.gl]");
if (!(fp = fopen(argv[1], "rb"))) {
fprintf(stderr, "dltogl: can't open %s\n", argv[1]);
exit(1);
}
gl = 0;
gl_fileno = 0;
if (argc == 3 && !(gl = fopen(argv[2], FOW))) {
fprintf(stderr, "dltogl: can't open %s for writing\n", argv[2]);
exit(1);
}
if (fgetc(fp) != 2)
die("dltogl: 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("dltogl: 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);
}
void die(s)
char*s;
{
fprintf(stderr,"%s\n",s);
exit(1);
}
#define BLOCKSIZE (8192)
void 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);
}
void 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);
}
int 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;
}
void writeshort(fp, s)
FILE* fp;
int s;
{
fputc(s & 255, fp);
fputc((s >> 8) & 255, fp);
}
void 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;
void 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);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment