/*   Decrunch Tetragon-files V1.0   */
/*  COMPILE with SAS V6.0 or later  */

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <string.h>
#include <exec/types.h>
#include <exec/memory.h>
#include <intuition/intuition.h>
#include <dos/dos.h>
#include <proto/exec.h>
#include <proto/intuition.h>
#include <proto/dos.h>
#include "env:date.h"

#define TETRAGON "TETRAGON"
#define POS_TETRAGON 229
#define POS_START 242
#define POS_STOP 248
#define POS_JUMP 284
#define POS_OBJLEN 52
#define OBJ_START 288
#define POS_CR1 95
#define POS_CR2 159
#define POS_CR3 225
#define POS_CR4 239
#define POS_CR5 162
#define POS_CR6 163

extern APTR LoadinMem(char *filename);
void exitheader(void);

const char *const verTag = "\0$VER: Detetragon 1.0 " __AMIGADATE__ ;

/* These are assembler routines that decrunch TETRAGON crunched files */
extern void __asm Decrunch1(
	register __d0 long cr1,
	register __d1 long cr2,
	register __d2 long cr3,
	register __d3 long cr5,
	register __d4 long cr6,
	register __a0 APTR srcend,
	register __a1 APTR tmpbuf);

extern void __asm Decrunch2(
	register __d2 long cr4,
	register __a0 APTR destbuf,
	register __a1 APTR tmpbuf,
	register __a2 APTR enddestbuf);

int main(int argc, char *argv[])
{	char *filename=NULL;
	char *myfilemem=NULL;
	BPTR mylock, myfile;
	long dst_len, tmp_len, snam_len, n, cr4;
	APTR dst_membuf, tmp_membuf, savename;
	int i;

	if(argc == 1) exitheader();

	for(i=1;i<=(argc-1);i++)
	{	if (*argv[i] == '?') exitheader();
	}

	for(i=1;i<=(argc-1);i++)
	{	/* LOAD FILE IN MEM */
		if (!(myfilemem = (char *)LoadinMem(filename = argv[i]))) exit(EXIT_FAILURE);

		/* CHECK FOR TETRAGON CRUNCHED FILE*/
		if (n=strncmp(myfilemem+POS_TETRAGON,TETRAGON,8))
		{	fprintf(stderr, "ERROR: File is not TETRAGON crunched!\n");
			FreeVec(myfilemem);
			exit(EXIT_FAILURE);
		}

		/* CREATE OUTPUT FILE */
		snam_len = strlen(filename);
		snam_len += 5;			/* Platz fuer .raw\0*/
		savename = AllocVec(snam_len, MEMF_ANY|MEMF_CLEAR);

		if (!savename)
		{	fprintf(stderr, "ERROR: Couldn't get enough mem for output-filename!\n");
			FreeVec(myfilemem);
			exit(EXIT_FAILURE);
		}

		strcpy(savename,filename);
		strcat(savename,".raw");

		if (mylock = Lock(savename,ACCESS_READ))
		{	fprintf(stderr, "ERROR: Output file already exists!\n");
			UnLock(mylock);
			FreeVec(savename);
			FreeVec(myfilemem);
			exit(EXIT_FAILURE);
		}

		if (!(myfile = Open(savename,MODE_NEWFILE)))
		{	fprintf(stderr, "ERROR: Couldn't create output file!\n");
			FreeVec(savename);
			FreeVec(myfilemem);
			exit(EXIT_FAILURE);
		}

		FreeVec(savename);

		/* INFORM USER ABOUT STATUS */
		printf("\nProcessing file...\n\n");
		printf("ABSOLUTE START ADDRESS     : $%p\n",*(long *)(myfilemem+POS_START));
		printf("ABSOLUTE STOP ADDRESS      : $%p\n",*(long *)(myfilemem+POS_STOP));
		printf("ABSOLUTE JUMPING ADDRESS   : $%p\n",*(long *)(myfilemem+POS_JUMP));

		/* ALLOC MEM FOR TMP-BUFFER */
		tmp_len = *(long *)(myfilemem+POS_STOP)-*(long *)(myfilemem+POS_START);
		tmp_membuf = AllocVec(tmp_len, MEMF_ANY|MEMF_CLEAR);

		if (!tmp_membuf)
		{	fprintf(stderr, "ERROR: Could not allocate enough memory for tmp buffer!\n");
			Close(myfile);
			FreeVec(myfilemem);
			exit(EXIT_FAILURE);
		}

		/* DECRUNCH PASS1 */
		Decrunch1(	*(myfilemem+POS_CR1),*(myfilemem+POS_CR2),*(myfilemem+POS_CR3),
					*(myfilemem+POS_CR5),*(myfilemem+POS_CR6),
					(APTR)(myfilemem+OBJ_START+(*(long *)(myfilemem+POS_OBJLEN))),
					tmp_membuf);

		cr4=*(myfilemem+POS_CR4);

		/* ALLOC MEM FOR DESTINATION-BUFFER */
		dst_len=tmp_len;
		dst_membuf=AllocVec(dst_len, MEMF_ANY|MEMF_CLEAR);

		/* RELEASE SOURCE FILE */
		FreeVec(myfilemem);

		if (!dst_membuf)
		{	fprintf(stderr, "ERROR: Could not allocate enough memory for destination buffer!\n");
			Close(myfile);
			FreeVec(tmp_membuf);
			exit(EXIT_FAILURE);
		}
		
		printf("LENGTH OF UNCRUNCHED OBJECT: %d BYTES\n",dst_len);

		/* DECRUNCH PASS2 */
		Decrunch2(cr4,dst_membuf,tmp_membuf,(APTR)((long)dst_membuf+dst_len));

		/* RELEASE TEMPORARY FILE */
		FreeVec(tmp_membuf);

		/* WRITE DESTINATION FILE */
		if ((n = Write(myfile,dst_membuf,dst_len)) == -1)
		{	fprintf(stderr, "ERROR: Couldn't write output file\n");
			Close(myfile);
			FreeVec(dst_membuf);
			exit(EXIT_FAILURE);
		}

		/* FREE RESOURCES */
		Close(myfile);
		FreeVec(dst_membuf);
	}
	exit(EXIT_SUCCESS);
}	

void exitheader(void)
{	fprintf(stderr, "DeTetragon ©1993 by Jürgen Lang\n");
	fprintf(stderr, "USAGE: detetragon <filename/s>\n");
	exit(EXIT_SUCCESS);
}

