Created
May 28, 2021 19:33
-
-
Save Sembiance/b4262c84ee5311ec6ee42f18db64c778 to your computer and use it in GitHub Desktop.
C code that converts a DL file to GL
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* 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