/*   Decrunch BYTEKILLER2-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 BYTEKILLER "NuSABB"
#define POS_BYTEKILLER 240
#define POS_START 42
#define POS_JUMP 208
#define POS_OBJLEN 272		/* length of object */
#define OBJ_START 268

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

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

/* These are assembler routines that decrunch BYTEKILLER crunched files */
extern void __asm Decrunch(register __a0 APTR src, register __a1 APTR dst);

int main(int argc, char *argv[])
{
	char *filename=NULL;
	char *myfilemem=NULL;
	BPTR mylock, myfile;
	long dst_len, snam_len, n;
	APTR dst_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 BYTEKILLER CRUNCHED FILE*/
		if (n=strncmp(myfilemem+POS_BYTEKILLER,BYTEKILLER,6))
		{	fprintf(stderr, "ERROR: File is not BYTEKILLER 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_OBJLEN)+*(long *)(myfilemem+POS_START));
		printf("ABSOLUTE JUMPING ADDRESS   : $%p\n",*(long *)(myfilemem+POS_JUMP));

		/* ALLOC MEM FOR DESTINATION-BUFFER */
		dst_len = (*(long *)(myfilemem+POS_OBJLEN)+*(long *)(myfilemem+POS_START)-*(long *)(myfilemem+POS_START));
		dst_membuf = AllocVec(dst_len, MEMF_ANY|MEMF_CLEAR);

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

		/* DECRUNCH */
		Decrunch((APTR)(myfilemem+OBJ_START),dst_membuf);

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

		/* 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, "DeBytekiller ©1993 by Jürgen Lang\n");
	fprintf(stderr, "USAGE: DeBytekiller <filename/s>\n");
	exit(EXIT_SUCCESS);
}
