/* writeim.c - write an Imagine 2.0 TDDD (3D Data Decription) file
 *           - by traversing the TTDDDLIB database
 *           - written by Glenn M. Lewis - 3/27/92
 *           - Added HINGE support - Rob Hounsell - 01/01/94
 */

#include <stdio.h>
#include <ctype.h>
#include "t3dlib.h"
#ifdef __STDC__
#include <stdlib.h>
#include <strings.h>
#include "writeim_protos.h"
#endif
#include <sys/types.h>
#include <sys/stat.h>

#ifdef AZTEC_C
#include <fcntl.h>
#include <exec/types.h>
#endif

static void process_INFO();
static void process_OBJ();
static void process_EXTR();
static void process_DESC();
static void process_ISTG();		/* Imagine staging file */

/* Here are a few necessary utilities */

static void put_name(world, name, size)
WORLD *world;
register char  *name;
register int size;
{
	while (*name && size) {
		fputc(*name++, world->inp);
		size--;
	}
	while (size--) fputc(0, world->inp);	/* Pad the rest of the string w/ 0 */
}

static void put_UBYTE(world, u)
WORLD *world;
UBYTE u;
{
	fputc((char)u, world->inp);
}

static void put_UWORD(world, w)
WORLD *world;
UWORD w;
{
	put_UBYTE(world, (UBYTE)(w>>8));
	put_UBYTE(world, (UBYTE)(w&0xFF));
}

static void put_ULONG(world, l)
WORLD *world;
ULONG l;
{
	put_UWORD(world, (UWORD)(l>>16));
	put_UWORD(world, (UWORD)(l&0xFFFF));
}

static void put_FRACT(world, f)
WORLD *world;
double f;
{
	put_ULONG(world, (ULONG)(f*65536.0));
}

static void put_XYZ(world, st)			/* Write a common string */
WORLD *world;
XYZ_st *st;
{
	put_FRACT(world, st->x);
	put_FRACT(world, st->y);
	put_FRACT(world, st->z);
}

static void put_RGB(world, st)			/* Write a common string */
WORLD *world;
RGB_st *st;
{
	put_UBYTE(world, 0);	/* PAD */
	put_UBYTE(world, st->r);
	put_UBYTE(world, st->g);
	put_UBYTE(world, st->b);
}

static void write_size(world, pos)
WORLD *world;
long pos;
{
	long size;
	long cur = ftell(world->inp);
	size = cur-pos;
	if (size&1) { size++; put_UBYTE(world, (UBYTE)0); }
	fseek(world->inp, pos-4L, 0);
	put_ULONG(world, (ULONG)size);
	fseek(world->inp, cur, 0);
}

/********************/
/* The MAIN section */
/********************/

int write_TDDD(world, myfile)
WORLD *world;
FILE *myfile;
{
	long pos, pos2;
	OBJECT *obj;
	struct stat statbuf;
#ifdef AMIGA
	int x;
#endif

	if (!world || !myfile) return(0);
	world->inp = myfile;

	if (world->info || world->object) {
		/* Don't write TDDD if there is nothing to write */

		/* Start the IFF TDDD file */
		put_name(world, "FORM", 4);
		put_ULONG(world, 0L);		/* Fill this in later [seek(,4L,0)] */
		pos = ftell(world->inp);	/* Save where this starting position is */
		put_name(world, "TDDD", 4);

		if (world->info) process_INFO(world, world->info);
		for (obj = world->object; obj; obj=obj->next) {
			put_name(world, "OBJ ", 4);
			put_ULONG(world, 0L);
			pos2 = ftell(world->inp);	/* Save for later */
			process_OBJ(world, obj);
			write_size(world, pos2);
		}
		write_size(world, pos);

	/* All done.  Close up shop. */
		fclose(world->inp);
	}

/* Also write the staging file if we have staging information */
	if (!world->istg) return(1);

	/* Check is the staging file already exists */
	if (stat("staging", &statbuf)==0) {
		fprintf(stderr, "WARNING: Moving existing 'staging' file to 'staging.bak'.\n");
#ifdef AMIGA
		/* We can only assume this will wait until process completes */
		x = system("copy staging staging.bak");
		if (x != 0) fprintf(stderr, "ERROR:  Staging file copy failed\n");
#else
		system("mv staging staging.bak");
		wait(1);
#endif
	}

	if (!(world->inp = fopen("staging", "w"))) {
		fprintf(stderr, "WARNING: Could not open 'staging' file for output.\n");
		fprintf(stderr, "No staging information saved!\n");
		world->inp = myfile;
		return(1);
	}

	/* Output the staging file... */
	/* Start the IFF ISTG file */
	put_name(world, "FORM", 4);
	put_ULONG(world, 0L);			/* Fill this in later [seek(,4L,0)] */
	pos = ftell(world->inp);		/* Save where this starting position is */
	put_name(world, "ISTG", 4);
	process_ISTG(world);
	write_size(world, pos);

	/* Return the file pointer back to normal... */
	fclose(world->inp);
	world->inp = myfile;
	return(1);
}

static void process_INFO(world, info)
WORLD *world;
INFO *info;
{
	register ULONG i;
	long pos;

	put_name(world, "INFO", 4);
	put_ULONG(world, 0L);
	pos = ftell(world->inp);	/* Save for later */

	for (i=0; i<8; i++)
		if (info->brsh[i][0]) {
			put_name(world, "BRSH", 4);
			put_ULONG(world, 82L);
			put_UWORD(world, (UWORD)i);
			put_name(world, info->brsh[i], 80);
		}

	for (i=0; i<8; i++)
		if (info->stnc[i][0]) {
			put_name(world, "STNC", 4);
			put_ULONG(world, 82L);
			put_UWORD(world, (UWORD)i);
			put_name(world, info->stnc[i], 80);
		}

	for (i=0; i<8; i++)
		if (info->txtr[i][0]) {
			put_name(world, "TXTR", 4);
			put_ULONG(world, 82L);
			put_UWORD(world, (UWORD)i);
			put_name(world, info->txtr[i], 80);
		}

	if (info->otrk[0]) {
		put_name(world, "OTRK", 4);
		put_ULONG(world, 18L);
		put_name(world, info->otrk, 18);
	}

	if (info->ambi) {
		put_name(world, "AMBI", 4);
		put_ULONG(world, 4L);
		put_RGB(world, info->ambi);
	}

	if (info->obsv) {
		put_name(world, "OBSV", 4);
		put_ULONG(world, 28L);
		put_XYZ(world, &info->obsv->came);
		put_XYZ(world, &info->obsv->rota);
		put_FRACT(world, info->obsv->foca);
	}

	if (info->ostr) {
		put_name(world, "OSTR", 4);
		put_ULONG(world, 56L);
		put_name(world, info->ostr->path, 18);
		put_XYZ(world, &info->ostr->tran);
		put_XYZ(world, &info->ostr->rota);
		put_XYZ(world, &info->ostr->scal);
		put_UWORD(world, info->ostr->info);
	}

	if (info->fade) {
		put_name(world, "FADE", 4);
		put_ULONG(world, 12L);
		put_FRACT(world, info->fade->at);
		put_FRACT(world, info->fade->by);
		put_RGB(world, &info->fade->to);
	}

	if (info->skyc) {
		put_name(world, "SKYC", 4);
		put_ULONG(world, 8L);
		put_RGB(world, &info->skyc->hori);
		put_RGB(world, &info->skyc->zeni);
	}

	if (info->glb0) {
		put_name(world, "GLB0", 4);
		put_ULONG(world, 8L);
		for (i=0; i<8; i++)
			put_UBYTE(world, (UBYTE)info->glb0[i]);
	}
	write_size(world, pos);
}

static void process_OBJ(world, obj)
WORLD *world;
OBJECT *obj;
{
	OBJECT *o;

	if (obj->extr) process_EXTR(world, obj);
	else process_DESC(world, obj);

	for (o=obj->child; o; o=o->next)
		process_OBJ(world, o);

	put_name(world, "TOBJ", 4);
	put_ULONG(world, 0L);
}

static void process_EXTR(world, obj)
WORLD *world;
OBJECT *obj;
{
	long pos;

	put_name(world, "EXTR", 4);
	put_ULONG(world, 0L);
	pos = ftell(world->inp);	/* Save for later */

	put_name(world, "LOAD", 4);
	put_ULONG(world, 80L);
	put_name(world, obj->extr->filename, 80);

	put_name(world, "MTRX", 4);
	put_ULONG(world, 60L);
	put_XYZ(world, &obj->extr->mtrx.tran);
	put_XYZ(world, &obj->extr->mtrx.scal);
	put_XYZ(world, &obj->extr->mtrx.rota1);
	put_XYZ(world, &obj->extr->mtrx.rota2);
	put_XYZ(world, &obj->extr->mtrx.rota3);

	write_size(world, pos);
}

static void process_DESC(world, obj)
WORLD *world;
OBJECT *obj;
{
	register int i, j;
	register DESC *desc;
	FGRP *fgrp;
	long pos;

	if (!obj) return;
	desc = obj->desc;
	if (!desc) return;

	put_name(world, "DESC", 4);
	put_ULONG(world, 0L);
	pos = ftell(world->inp);	/* Save for later */

	if (desc->name) {
		put_name(world, "NAME", 4);
		put_ULONG(world, 18L);
		put_name(world, desc->name, 18);
	}

	if (desc->posi) {
		put_name(world, "POSI", 4);
		put_ULONG(world, 12L);
		put_XYZ(world, desc->posi);
	}

	if (desc->size) {
		put_name(world, "SIZE", 4);
		put_ULONG(world, 12L);
		put_XYZ(world, desc->size);
	}

	if (desc->colr) {
		put_name(world, "COLR", 4);
		put_ULONG(world, 4L);
		put_RGB(world, desc->colr);
	}

	if (desc->refl) {
		put_name(world, "REFL", 4);
		put_ULONG(world, 4L);
		put_RGB(world, desc->refl);
	}

	if (desc->tran) {
		put_name(world, "TRAN", 4);
		put_ULONG(world, 4L);
		put_RGB(world, desc->tran);
	}

	if (desc->spc1) {
		put_name(world, "SPC1", 4);
		put_ULONG(world, 4L);
		put_RGB(world, desc->spc1);
	}

	if (desc->ints) {
		put_name(world, "INTS", 4);
		put_ULONG(world, 4L);
		put_FRACT(world, (*desc->ints));
	}

	/* Mandatory field... stuff it, regardless */
	if (desc->shap) {
		put_name(world, "SHAP", 4);
		put_ULONG(world, 4L);
		put_UWORD(world, (UWORD)desc->shap[0]);
		put_UWORD(world, (UWORD)desc->shap[1]);
	} else {
		put_name(world, "SHAP", 4);
		put_ULONG(world, 4L);
		put_UWORD(world, (UWORD)2);
		put_UWORD(world, (UWORD)1);
	}

	if (desc->axis) {
		put_name(world, "AXIS", 4);
		put_ULONG(world, 36L);
		put_XYZ(world, &desc->axis->xaxi);
		put_XYZ(world, &desc->axis->yaxi);
		put_XYZ(world, &desc->axis->zaxi);
	}

	if (desc->tpar) {
		put_name(world, "TPAR", 4);
		put_ULONG(world, 64L);
		for (i=0; i<16; i++) put_FRACT(world, desc->tpar[i]);
	}

	if (desc->surf) {
		put_name(world, "SURF", 4);
		put_ULONG(world, 5L);
		for (i=0; i<5; i++) put_UBYTE(world, desc->surf[i]);
		put_UBYTE(world, (UBYTE)0);	/* To make this chunk even-sized */
	}

	if (desc->mttr) {
		put_name(world, "MTTR", 4);
		put_ULONG(world, 2L);
		put_UBYTE(world, desc->mttr->type);
		put_UBYTE(world, (UBYTE)(((int)((desc->mttr->indx-1.0)*100.0))&0xFF));
	}

	if (desc->spec) {
		put_name(world, "SPEC", 4);
		put_ULONG(world, 2L);
		put_UBYTE(world, desc->spec[0]);
		put_UBYTE(world, desc->spec[1]);
	}

	if (desc->prp0) {
		put_name(world, "PRP0", 4);
		put_ULONG(world, 6L);
		for (i=0; i<6; i++) put_UBYTE(world, desc->prp0[i]);
	}

	if (desc->prp1) {
		put_name(world, "PRP1", 4);
		put_ULONG(world, 8L);
		for (i=0; i<8; i++) put_UBYTE(world, desc->prp1[i]);
	}

	if (desc->stry) {
		put_name(world, "STRY", 4);
		put_ULONG(world, 56L);
		put_name(world, desc->stry->path, 18);
		put_XYZ(world, &desc->stry->tran);
		put_XYZ(world, &desc->stry->rota);
		put_XYZ(world, &desc->stry->scal);
		put_UWORD(world, desc->stry->info);
	}

	if (desc->pcount) {
		put_name(world, "PNTS", 4);
		put_ULONG(world, (ULONG)desc->pcount*12L+2L);
		put_UWORD(world, desc->pcount);
		for (i=0; i<desc->pcount; i++)
			put_XYZ(world, &desc->pnts[i]);
	}

	if (desc->ecount) {
		put_name(world, "EDGE", 4);
		put_ULONG(world, (ULONG)desc->ecount*4L+2L);
		put_UWORD(world, desc->ecount);
		for (i=0; i<2*desc->ecount; i++)
			put_UWORD(world, desc->edge[i]);
	}

	if (desc->eflg) {
		put_name(world, "EFLG", 4);
		put_ULONG(world, (ULONG)desc->eflg->num+2L);
		put_UWORD(world, desc->eflg->num);
		for (i=0; i<desc->eflg->num; i++)
			put_UBYTE(world, desc->eflg->eflg[i]);
		if (desc->eflg->num&1) put_UBYTE(world, 0);	/* Pad on even boundary */
	}

	if (desc->fcount) {
		put_name(world, "FACE", 4);
		put_ULONG(world, (ULONG)desc->fcount*6L+2L);
		put_UWORD(world, desc->fcount);
		for (i=0; i<3*desc->fcount; i++)
			put_UWORD(world, desc->face[i]);

		if (desc->clst) {
			put_name(world, "CLST", 4);
			put_ULONG(world, (ULONG)desc->fcount*3L+2L);
			put_UWORD(world, desc->fcount);
			for (i=0; i<3*desc->fcount; i++)
				put_UBYTE(world, desc->clst[i]);
			if (desc->fcount&1) put_UBYTE(world, 0);	/* Pad to even length */
		}
		if (desc->rlst) {
			put_name(world, "RLST", 4);
			put_ULONG(world, (ULONG)desc->fcount*3L+2L);
			put_UWORD(world, desc->fcount);
			for (i=0; i<3*desc->fcount; i++)
				put_UBYTE(world, desc->rlst[i]);
			if (desc->fcount&1) put_UBYTE(world, 0);	/* Pad to even length */
		}
		if (desc->tlst) {
			put_name(world, "TLST", 4);
			put_ULONG(world, (ULONG)desc->fcount*3L+2L);
			put_UWORD(world, desc->fcount);
			for (i=0; i<3*desc->fcount; i++)
				put_UBYTE(world, desc->tlst[i]);
			if (desc->fcount&1) put_UBYTE(world, 0);	/* Pad to even length */
		}
	}

	for (fgrp=desc->fgrp; fgrp; fgrp=fgrp->next) {
		put_name(world, "FGRP", 4);
		put_ULONG(world, (ULONG)fgrp->num*2L+2L+18L);
		put_UWORD(world, fgrp->num);
		put_name(world, fgrp->name, 18);
		for (i=0; i<fgrp->num; i++)
			put_UWORD(world, fgrp->face[i]);
	}

	for (i=0; i<4; i++) {
		if (!desc->txt2[i]) continue;
		put_name(world, "TXT2", 4);
		j = strlen(desc->txt2[i]->Name);
/* CWC */	j = 144L+17L+j;  /* Oddly enough, an odd number is allowed here */
/* CWC 		put_ULONG(world, 94L+18L+j+(1-(j&1)));    original line */
/* CWC */	put_ULONG(world, j);
		put_UWORD(world, desc->txt2[i]->Flags);
		put_XYZ(world, &desc->txt2[i]->TAxis.tran);
		put_XYZ(world, &desc->txt2[i]->TAxis.rota1);
		put_XYZ(world, &desc->txt2[i]->TAxis.rota2);
		put_XYZ(world, &desc->txt2[i]->TAxis.rota3);
		put_XYZ(world, &desc->txt2[i]->TAxis.scal);
		for (j = 0; j < 16; j++) put_FRACT(world, desc->txt2[i]->Params[j]);
		for (j = 0; j < 16; j++) put_UBYTE(world, desc->txt2[i]->PFlags[j]);
/* CWC		put_name(world, desc->txt2[i]->SubName, 18); original line */
/* CWC */	put_name(world, desc->txt2[i]->SubName, 17);  /* Yes, this 
                                                                 is correct! */
		j = strlen(desc->txt2[i]->Name);
		put_UWORD(world, j);
		put_name(world, desc->txt2[i]->Name, j);
/* CWC */       j = j + 144L + 17L;
		if (j&1) put_UBYTE(world, 0);	/* Pad the odd byte */
	}

	write_size(world, pos);
}

/************************************************************************/
/* New code to write staging file - written by Glenn M. Lewis - 8/11/92 */
/* Added HINGE support - Rob Hounsell - 01/01/94                        */
/************************************************************************/

static void process_OSIZ();
static void process_POSN();
static void process_ALGN();
static void process_PALN();
static void process_TALN();
static void process_HING();
static void process_PTH2();
static void process_GLB2();
static void process_AXIS();
static void process_LITE();
static void process_FILE();

static void process_ISTG(world)
WORLD *world;
{
	register ISTG *istg = world->istg;
	register SOBJ *sobj;
	long pos2;

	if (!world->inp) return;	/* File not open */

	put_name(world, "MAXF", 4);
	put_ULONG(world, 2L);
	put_UWORD(world, istg->maxf);

	/* Sort the SOBJ's first? */

/* Here is the main loop: */
	for (sobj=istg->head; sobj; sobj=sobj->next) {
		put_name(world, "SOBJ", 4);
		put_ULONG(world, 0L);

		pos2 = ftell(world->inp);	/* Save for later */

		put_name(world, "NAME", 4);
		put_ULONG(world, 18L);
		put_name(world, sobj->name, 18);
		put_name(world, "STGF", 4);
		put_ULONG(world, 2L);
		put_UWORD(world, sobj->stgf);
		if (sobj->glb2) process_GLB2(sobj, world);
		if (sobj->file) process_FILE(sobj, world);
		if (sobj->lite) process_LITE(sobj, world);
		if (sobj->axis) process_AXIS(sobj, world);
		if (sobj->pth2) process_PTH2(sobj, world);
		if (sobj->posn) process_POSN(sobj, world);
		if (sobj->taln) process_TALN(sobj, world);
		if (sobj->algn) process_ALGN(sobj, world);
		if (sobj->osiz) process_OSIZ(sobj, world);
		if (sobj->paln) process_PALN(sobj, world);
		if (sobj->hing) process_HING(sobj, world);

		write_size(world, pos2);
	}

/* All done. */
}

static void process_OSIZ(sobj, world)
SOBJ *sobj;
WORLD *world;
{
	register OSIZ *osiz;

	for (osiz=sobj->osiz; osiz; osiz=osiz->next) {
		put_name(world, "OSIZ", 4);
		put_ULONG(world, 18L);
		put_UWORD(world, osiz->flags);
		put_UWORD(world, osiz->start);
		put_UWORD(world, osiz->stop);
		put_XYZ(world, &osiz->size);
	}
}

static void process_POSN(sobj, world)
SOBJ *sobj;
WORLD *world;
{
	register POSN *posn;

	for (posn=sobj->posn; posn; posn=posn->next) {
		put_name(world, "POSN", 4);
		put_ULONG(world, 18L);
		put_UWORD(world, posn->flags);
		put_UWORD(world, posn->start);
		put_UWORD(world, posn->stop);
		put_XYZ(world, &posn->posn);
	}
}

static void process_ALGN(sobj, world)
SOBJ *sobj;
WORLD *world;
{
	register ALGN *algn;

	for (algn=sobj->algn; algn; algn=algn->next) {
		put_name(world, "ALGN", 4);
		put_ULONG(world, 18L);
		put_UWORD(world, algn->flags);
		put_UWORD(world, algn->start);
		put_UWORD(world, algn->stop);
		put_XYZ(world, &algn->algn);
	}
}

static void process_PALN(sobj, world)
SOBJ *sobj;
WORLD *world;
{
	register PALN *paln;

	for (paln=sobj->paln; paln; paln=paln->next) {
		put_name(world, "PALN", 4);
		put_ULONG(world, 6L);
		put_UWORD(world, paln->flags);
		put_UWORD(world, paln->start);
		put_UWORD(world, paln->stop);
	}
}

static void process_TALN(sobj, world)
SOBJ *sobj;
WORLD *world;
{
	register TALN *taln;
	int len;

	for (taln=sobj->taln; taln; taln=taln->next) {
		len = strlen(taln->trackobj);
		put_name(world, "TALN", 4);
		put_ULONG(world, (ULONG)15L+(long)len+(long)((len&1)? 0 : 1));
		put_UWORD(world, taln->flags);
		put_UWORD(world, taln->start);
		put_UWORD(world, taln->stop);
		put_FRACT(world, taln->initial_y);
		put_FRACT(world, taln->final_y);
		/* BCPL string... byte (length) followed by string, then zero */

		/* N.B. trailing zero is not present in original staging file */
		/* except to pad chunk out to a word boundary. [Rob Hounsell] */
		put_UBYTE(world, (UBYTE)len);
		put_name(world, taln->trackobj, len);
		/* need pad byte only if size of the string is even, since one  */
		/* byte is used up by the length value.                         */
		if (!(len&1)) put_UBYTE(world, 0);		/* pad byte */
	}
}

static void process_HING(sobj, world)
SOBJ *sobj;
WORLD *world;
{
	register HING *hing;
	int len;

	for (hing=sobj->hing; hing; hing=hing->next) {
		len = strlen(hing->hingeobj);
		put_name(world, "HING", 4);
		put_ULONG(world, (ULONG)7L+(long)len+(long)((len&1)? 0 : 1));
		put_UWORD(world, hing->flags);
		put_UWORD(world, hing->start);
		put_UWORD(world, hing->stop);
		/* BCPL string... byte (length) followed by string, then zero */
		/* Not really. See process_TALN or process_PTH2! [Rob Hounsell] */
		put_UBYTE(world, (UBYTE)len);
		put_name(world, hing->hingeobj, len);
		if (!(len&1)) put_UBYTE(world, 0);		/* pad byte */
	}
}

static void process_PTH2(sobj, world)
SOBJ *sobj;
WORLD *world;
{
	register PTH2 *pth2;
	int len;

	for (pth2=sobj->pth2; pth2; pth2=pth2->next) {
		len = strlen(pth2->path);
		put_name(world, "PTH2", 4);
		put_ULONG(world, (ULONG)23L+(long)len+(long)((len&1) ? 0 : 1));
		put_UWORD(world, pth2->flags);
		put_UWORD(world, pth2->start);
		put_UWORD(world, pth2->stop);
		put_ULONG(world, pth2->acceleration_frames);
		put_FRACT(world, pth2->start_speed);
		put_ULONG(world, pth2->deacceleration_frames);
		put_FRACT(world, pth2->end_speed);
		/* BCPL string... byte (length) followed by string, then zero */
		/* N.B. trailing zero is not present in original staging file */
		/* except to pad chunk out to a word boundary. [Rob Hounsell] */
		put_UBYTE(world, (UBYTE)len);
		put_name(world, pth2->path, len);
		/* need pad byte only if size of the string is even, since one  */
		/* byte is used up by the length value.                         */
		if (!(len&1)) put_UBYTE(world, 0);		/* pad byte */
	}
}

static void process_GLB2(sobj, world)
SOBJ *sobj;
WORLD *world;
{
	register GLB2 *glb2;
	int len;

	for (glb2=sobj->glb2; glb2; glb2=glb2->next) {
		len = strlen(glb2->globalbrush);
		put_name(world, "GLB2", 4);
		put_ULONG(world, (ULONG)356L+len);
		put_UWORD(world, glb2->flags);
		put_UWORD(world, glb2->start);
		put_UWORD(world, glb2->stop);
		put_ULONG(world, glb2->sky_blending);
		put_FRACT(world, glb2->starfield);
		put_ULONG(world, glb2->transition);
		/* These colors are stored as FRACTs */
		put_XYZ(world, &glb2->ambient);
		put_XYZ(world, &glb2->horizon);
		put_XYZ(world, &glb2->zenith1);
		put_XYZ(world, &glb2->zenith2);
		put_XYZ(world, &glb2->fog_color);
		put_FRACT(world, glb2->fog_bottom);
		put_FRACT(world, glb2->fog_top);
		put_FRACT(world, glb2->fog_length);
		put_ULONG(world, glb2->brush_seq);
		put_ULONG(world, glb2->backdrop_seq);
		put_name(world, glb2->backdrop, 256);		/* Fixed size */
		/* BCPL string... byte (length) followed by string, then zero */
		put_UBYTE(world, (UBYTE)len);
		put_name(world, glb2->globalbrush, len);	/* Var. size */
		put_UBYTE(world, 0);
		if (len&1) put_UBYTE(world, 0);		/* pad byte */
	}
}

static void process_AXIS(sobj, world)
SOBJ *sobj;
WORLD *world;
{
	register SAXIS *axis;

	for (axis=sobj->axis; axis; axis=axis->next) {
		put_name(world, "AXIS", 4);
		put_ULONG(world, 6L);
		put_UWORD(world, axis->flags);
		put_UWORD(world, axis->start);
		put_UWORD(world, axis->stop);
	}
}

static void process_LITE(sobj, world)
SOBJ *sobj;
WORLD *world;
{
	register LITE *lite;

	for (lite=sobj->lite; lite; lite=lite->next) {
		put_name(world, "LITE", 4);
		put_ULONG(world, 22L);
		put_UWORD(world, lite->flags);
		put_UWORD(world, lite->start);
		put_UWORD(world, lite->stop);
		/* This color is stored as a FRACT */
		put_XYZ(world, &lite->color);
		put_ULONG(world, lite->transition);
	}
}

static void process_FILE(sobj, world)
SOBJ *sobj;
WORLD *world;
{
	register SFILE *file;
	int len;

	for (file=sobj->file; file; file=file->next) {
		len = strlen(file->object_description);
		put_name(world, "FILE", 4);
		put_ULONG(world, (ULONG)20L+len-(len&1));
		put_UWORD(world, file->flags);
		put_UWORD(world, file->start);
		put_UWORD(world, file->stop);
		put_FRACT(world, file->cycles_to_perform);
		put_FRACT(world, file->initial_cycle_phase);
		put_ULONG(world, file->transition);
		/* BCPL string... byte (length) followed by string */
		put_UBYTE(world, (UBYTE)len);
		put_name(world, file->object_description, len);
		if (!(len&1)) put_UBYTE(world, 0);		/* pad byte */
	}
}

