/*

  This is a part of the Project Frontier's Source code.

  Copyright (C) 1997-98 Francis Gastellu
                    aka Lone Runner/Aegis

  This program is free software; you can redistribute it and/or
  modify it under the terms of the GNU General Public License
  as published by the Free Software Foundation; either version 2
  of the License, or (at your option) any later version.

  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with this program; if not, write to the Free Software
  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

*/

// PPLX Sources

#include <stdio.h>
#include <process.h>
#include <iostream.h>
#include <alloc.h>
#include <dir.h>
#include <string.h>
#include <stdlib.h>
#include <dos.h>
#include <conio.h>
#include <math.h>
#include "pplx.h"
#include "vfs.h"
#include "fortify.h"

//#define IDE

#define SIZE 		8192
#define PARAMLEN 	256
#define LINESIZE 	256

#ifdef IDE

#define MAXIT 30

#else
extern unsigned _stklen = 16384;
#define MAXIT 200

#endif

struct varRecord{
	int	 ID;
	int	 Type;
	int  nDim;
	int  dim[3];
	char data[8];
	char isConst;
	int function;
	int local;
	int index;
	int predef;
	};

_file *_in=NULL;

struct varDecType
	{
	unsigned int	varNumber;
	char			nDim;
	int				dim1;
	int				dim2;
	int				dim3;
	unsigned int	varType;
	} varDec ;

struct varDecNumType
	{
	unsigned int	typeID;
	unsigned int	varType;
	double			constVal;
	} varDecNum;

struct varDecNumType1
	{
	unsigned int	typeID;
	unsigned int	varType;
	long			constVal;
	} varDecNum1;

char far memError[] = "\nFATAL ERROR 1 : Memory allocation\n";
char far fullBuffer[] = "\nFATAL ERROR 5: Buffer full\n";
char far AegisDevise[] = ";                 AEGiS Corp - Break the routines, code against the machines!\n";
char far remLine[] = ";------------------------------------------------------------------------------\n";
char far blankLine[] = "                                                                               \n";
extern char errDisk[];
char *buffer;
char *buffer2;
char far *param[100];
int argNum;
FILE *in, *out;
int s;
int pass;
varRecord *variable;
unsigned int far gotoTable[999];
unsigned int far procTable[999];
int format;
int totalVar;
char far filename[256];
char far filenameSource[256];
char far originalName[256];
int decal;
int index[0x11] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
char* temp;
char* temp2;
char far spr[256];
char flag[20]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
char flagL[20]={'F','W','R','D','A','B','M','S','C','I','P','c','a','f','d','p','H','i','s',0};
char *vide;
int gotoIndex=0;
int procIndex=0;
int error=0;
int debug=0;
int nVars=0;
int noanalysis=0;
int iterNum=0;
int warning =0;
int compilerError=0;
extern int postError;
int pIndex=0;
int DontRemove;
int leavePPU=0;
int onlyPPU=0;
int noPost=0;
int antiDstripped=0;
int writeBug=0;
int toUnConst=0;
int xor17=0;
extern int maxElse;
int fileNum=0;

char* decompOperator(int count, long& bufPtr, int type, int parenthes);
int isVariable(signed int w1, signed int w2);
void getPair(signed int&, signed int&);
char* varContents(int varNum);
int gotoInTable(int a);
int getGotoIndex(int a);
int procInTable(int a);
int getProcIndex(int a);
char *reverseFunction(int& count);
void *my_alloc(long size);
char *toVar(int var);
void checkFunction(int function);
char *my_free(void *ptr);
void mystrcat(char *&dest, char *src);
void mystrncat(char *&dest, char *src, int count);
void mystrcpy(char *&dest, char *src);
void mystrncpy(char *&dest, char *src, int count);
int sort_function( const void *a, const void *b);
void errorMessage(char *str);
void post(char *file);
void status(int n, int forcefull, int forceEmpty);;
void cursorOff(void);
void cursorOn(void);

char far *pTable[512];


char* decompFunction(int count, long& bufPtr)
{
signed int b,a,c;

iterNum++;
if (iterNum == MAXIT && pass == 1)
	{
    antiDstripped++;
	warning++;
	}

if (iterNum >= MAXIT)
	{
	vide = (char *)calloc(2,1);
	mystrcpy(vide,"");
	return vide;
	}

pTable[++pIndex] = (char*) calloc(LINESIZE,1);
pTable[++pIndex] = (char*) calloc(LINESIZE,1);

mystrcpy(pTable[pIndex-1],")");

for (b=0;b<count;b++)
	{
	bufPtr -=2;

	if (bufPtr < 0)
        errorMessage("Failed!\nFATAL ERROR 3: Shifted buffer\n");

	memcpy(&a,&buffer[bufPtr], 2);
	if (a < 0)
		 {
		 if (~a+1 >= 20)
			{
			checkFunction(a);
			mystrcpy(pTable[pIndex],Function[~a+1].name);
			temp = decompFunction(Function[~a+1].argMini, bufPtr);
			mystrcat(pTable[pIndex],temp);
			mystrcpy(temp,pTable[pIndex]);
			}
		 else
			{
			temp = decompOperator(Function[~a+1].argMini, bufPtr, ~a+1,0);
			}


		 mystrcpy(pTable[pIndex], pTable[pIndex-1]);

		 mystrcpy(pTable[pIndex-1], temp);
		 if (b != 0)
		   mystrcat(pTable[pIndex-1], ", ");
		 mystrcat(pTable[pIndex-1],pTable[pIndex]);
		 temp=my_free(temp);


		 }
	else
		 {
		  bufPtr -=2;
		  memcpy(&a,&buffer[bufPtr], 2);
		  mystrcpy(pTable[pIndex], pTable[pIndex-1]);
		  if (pass == 2 && variable[a].isConst == 1)
			{
			temp = varContents(a);
			mystrcpy(pTable[pIndex-1], temp);
			temp=my_free(temp);
			}
		  else
			{
			if (variable[a].Type == 0x0F)
				{
				if (variable[a].isConst != 2) variable[a].isConst = 0;
				temp2 = (char *)calloc(256,1);
				sprintf(temp2,"FUNCTION%03d(",variable[a].index);
				mystrcpy(pTable[pIndex-1],temp2);
				temp2=my_free(temp2);
				memcpy(&c,variable[a].data,2);
				c &= 0xFF;
				if (c > 0)
					{
					temp =decompFunction(c,bufPtr);
					mystrcat(pTable[pIndex-1],temp);
					temp=my_free(temp);
					}
				else
					mystrcat(pTable[pIndex-1],")");
				}
			else
				{
				if (variable[a].nDim > 0)
					{
					if (variable[a].isConst != 2) variable[a].isConst = 0;
					temp2 = toVar(a);
					mystrcpy(pTable[pIndex-1],temp2);
					temp2=my_free(temp2);
					c = variable[a].nDim;
					if (c > 0)
						{
						temp = decompFunction(c,bufPtr);
						mystrcat(pTable[pIndex-1],temp);
						temp=my_free(temp);
						}
					else
						mystrcat(pTable[pIndex-1],")");
					}
				else
					if (variable[a].function == 0)
						{
						temp2 = toVar(a);
						mystrcpy(pTable[pIndex-1],temp2);
						temp2=my_free(temp2);
						}
					else
						{
						temp2 = (char *)calloc(256,1);
						sprintf(temp2,"FUNCTION%03d",variable[variable[a].function].index);
						mystrcpy(pTable[pIndex-1],temp2);
						temp2=my_free(temp2);
						}
				}
			}

		  if (b != 0)
			mystrcat(pTable[pIndex-1], ", ");
		  mystrcat(pTable[pIndex-1],pTable[pIndex]);
		 }
	}
  my_free(pTable[pIndex--]);
  return pTable[pIndex--];
}


char* decompOperator(int count, long& bufPtr, int type, int parenthes)
{
signed int b,a;

iterNum++;
if (iterNum == MAXIT && pass == 1)
	{
    antiDstripped++;
	warning++;
	}

if (iterNum >= MAXIT)
	{
	vide = (char *)calloc(2,1);
	mystrcpy(vide,"");
	return vide;
	}

pTable[++pIndex] = (char*) calloc(LINESIZE,1);
pTable[++pIndex] = (char*) calloc(LINESIZE,1);

mystrcpy(pTable[pIndex-1],"");

if (bufPtr == 0)
	{
	if (pass == 2)
		{
		warning++;
        compilerError++;
        writeBug=1;
		}
	mystrcpy(pTable[pIndex-1],Function[type].name);
	my_free(pTable[pIndex--]);
	return pTable[pIndex--];
	}

mystrcpy(pTable[pIndex],"");

checkFunction(~type+1);
mystrcpy(pTable[pIndex-1]," ");
mystrcat(pTable[pIndex-1],Function[type].name);
mystrcat(pTable[pIndex-1]," ");

bufPtr -=2;
memcpy(&a,&buffer[bufPtr], 2);

if (a < 0)
	if (~a+1 < 20)
		{
		temp = decompOperator(Function[~a+1].argMini, bufPtr, ~a+1, ((type >= 4) && (type <= 7)) && ((~a+1 >= 6) || (~a+1 <= 9)) );
		mystrcat(pTable[pIndex-1],temp);
		temp=my_free(temp);
		}
	else
		{
		checkFunction(a);
		temp = decompFunction(Function[~a+1].argMini, bufPtr);
		mystrcat(pTable[pIndex-1], Function[~a+1].name);
		mystrcat(pTable[pIndex-1],temp);
		temp=my_free(temp);
		}
else
	{
	bufPtr -=2;
	memcpy(&a,&buffer[bufPtr], 2);

	if (pass == 2 && variable[a].isConst == 1)
		{
		temp = varContents(a);
		mystrcat(pTable[pIndex-1], temp);
		temp=my_free(temp);
		}
	else
		{
		if (variable[a].Type == 0x0F)
			{
			if (variable[a].isConst != 2) variable[a].isConst = 0;
			temp2 = (char *)calloc(256,1);
			sprintf(temp2,"FUNCTION%03d(",variable[a].index);
			mystrcat(pTable[pIndex-1],temp2);
			temp2=my_free(temp2);
			memcpy(&b,variable[a].data,2);
			b &= 0xFF;
			if (b > 0)
				{
				temp =decompFunction(b,bufPtr);
				mystrcat(pTable[pIndex-1],temp);
				temp=my_free(temp);
				}
			else
				mystrcat(pTable[pIndex-1],")");
			}
		else
			{
			if (variable[a].nDim > 0)
				{
				if (variable[a].isConst != 2) variable[a].isConst = 0;
				temp2 = toVar(a);
				mystrcat(pTable[pIndex-1],temp2);
				temp2=my_free(temp2);
				b = variable[a].nDim;
				if (b > 0)
					{
					temp = decompFunction(b,bufPtr);
					mystrcat(pTable[pIndex-1],temp);
					temp=my_free(temp);
					}
				else
					mystrcat(pTable[pIndex-1],")");
				}
			else
				if (variable[a].function == 0)
					{
					temp2 = toVar(a);
					mystrcat(pTable[pIndex-1],temp2);
					temp2=my_free(temp2);
					}
				else
					{
					temp2 = (char *)calloc(256,1);
					sprintf(temp2,"FUNCTION%03d",variable[variable[a].function].index);
					mystrcat(pTable[pIndex-1],temp2);
					temp2=my_free(temp2);
					}
			}
		}
	}

if (Function[type].argMini == 2 && bufPtr > 0)
	{
	mystrcpy(pTable[pIndex], pTable[pIndex-1]);
	bufPtr -=2;
	memcpy(&a,&buffer[bufPtr], 2);

	if (a < 0)
		if (~a+1 < 20)
			{
			temp = decompOperator(Function[~a+1].argMini, bufPtr, ~a+1, ((type >= 4) && (type <= 7)) && ((~a+1 >= 6) || (~a+1 <= 9)) );
			mystrcpy(pTable[pIndex-1],temp);
			temp=my_free(temp);
			}
		else
			{
			checkFunction(a);
			temp = decompFunction(Function[~a+1].argMini, bufPtr);
			mystrcpy(pTable[pIndex-1], Function[~a+1].name);
			mystrcat(pTable[pIndex-1],temp);
			temp=my_free(temp);
			}
	else
		{
		bufPtr -=2;
		memcpy(&a,&buffer[bufPtr], 2);
		if (pass == 2 && variable[a].isConst == 1)
			{
			temp = varContents(a);
			mystrcpy(pTable[pIndex-1], temp);
			temp=my_free(temp);
			}
		else
			{
			if (variable[a].Type == 0x0F)
				{
				if (variable[a].isConst != 2) variable[a].isConst = 0;
				temp2 = (char *)calloc(256,1);
				sprintf(temp2,"FUNCTION%03d(",variable[a].index);
				mystrcpy(pTable[pIndex-1],temp2);
				temp2=my_free(temp2);
				memcpy(&b,variable[a].data,2);
				b &= 0xFF;
				if (b > 0)
					{
					temp =decompFunction(b,bufPtr);
					mystrcat(pTable[pIndex-1],temp);
					temp=my_free(temp);
					}
				else
					mystrcat(pTable[pIndex-1],")");
				}
			else
				{
				if (variable[a].nDim > 0)
					{
					if (variable[a].isConst != 2) variable[a].isConst = 0;
					temp2 = toVar(a);
					mystrcpy(pTable[pIndex-1],temp2);
					temp2=my_free(temp2);
					b = variable[a].nDim;
					if (b > 0)
						{
						temp = decompFunction(b,bufPtr);
						mystrcat(pTable[pIndex-1],temp);
						temp=my_free(temp);
						}
					else
						mystrcat(pTable[pIndex-1],")");
					}
				else
					{
					if (variable[a].function == 0)
						{
						temp2 = toVar(a);
						mystrcpy(pTable[pIndex-1],temp2);
						temp2=my_free(temp2);
						}
					else
						{
						temp2 = (char *)calloc(256,1);
						sprintf(temp2,"FUNCTION%03d",variable[variable[a].function].index);
						mystrcpy(pTable[pIndex-1],temp2);
						temp2=my_free(temp2);
						}
					}
				}
			}
		}

	mystrcat(pTable[pIndex-1], pTable[pIndex]);
	mystrcpy(pTable[pIndex],"(");
	mystrcat(pTable[pIndex],pTable[pIndex-1]);
	mystrcat(pTable[pIndex],")");
	mystrcpy(pTable[pIndex-1], pTable[pIndex]);
	}
else
	{
	mystrncpy(pTable[pIndex],&pTable[pIndex-1][1],1);
//	mystrcat(pTable[pIndex], "(");
	mystrcat(pTable[pIndex], &pTable[pIndex-1][3]);
//	mystrcat(pTable[pIndex], ")");
	mystrcpy(pTable[pIndex-1], pTable[pIndex]);


	}

	memcpy(&b,&buffer[bufPtr-2], 2);
    if ((~a+1 >= 20) && (~a+1 <= HiFunction) && (Function[~a+1].argMini == 0) && (b == 0))
    	{
		memcpy(&b,&buffer[bufPtr-4], 2);
        if (b == 0)
	    	bufPtr -=2;
        }

    int locBuf=bufPtr;
   	int processIt=0;

	while (bufPtr > 0)
		{
		locBuf -=2;
		memcpy(&a,&buffer[locBuf], 2);
		memcpy(&b,&buffer[locBuf-2], 2);
		if (!(~a+1 < 20 && ~a+1 >= 0))
			break;
		if (Function[~a+1].argMini > 1)
			break;
        if (a == 0 && b == 0)
        	{
        	processIt=1;
        	break;
            }
        b = ~b+1;
        if (a == 0 && (b > 0 && b < 20))
        	{
        	processIt=1;
        	break;
            }
		}

if (processIt)
	{

DontRemove = 0;

	while (bufPtr > 0)
		{
		bufPtr -=2;
		memcpy(&a,&buffer[bufPtr], 2);
		if (!(~a+1 < 20 && ~a+1 > 0))
        	{
			bufPtr +=2;
			break;
            }
		if (Function[~a+1].argMini > 1)
			{
			bufPtr +=2;
			break;
			}

        if (pass == 2)
		    {
		    compilerError++;
            writeBug=1;
            }

	    mystrcpy(pTable[pIndex],Function[~a+1].name);
		mystrcat(pTable[pIndex],pTable[pIndex-1]);
		mystrcpy(pTable[pIndex-1], pTable[pIndex]);
		DontRemove = 1;
		}
    }

//  Enleve les parentheses
if (!parenthes && !((type >= 10) && (type <= 18)) && !(type == 2) && !(type == 3) && !DontRemove)
	{
	mystrcpy(pTable[pIndex], &pTable[pIndex-1][1]); // -1 = resultT
	pTable[pIndex][strlen(pTable[pIndex])-1] = 0;
	mystrcpy(pTable[pIndex-1], pTable[pIndex]);
	}

  my_free(pTable[pIndex--]);
  return pTable[pIndex--];
#pragma warn -par
}
#pragma warn .par



signed int decompLigne(long bufPtr, signed int type)
{
signed int a,b,c;
int varFlag=0;

bufPtr -=4;

for (c=0;;c++)
	 {
     if (type == 8 && c == 1)
     	varFlag=1;
     else
     	varFlag=0;
	 iterNum=0;
	 memcpy(&a,&buffer[bufPtr], 2);
	 if (a == 0) bufPtr -=2;
	 memcpy(&a,&buffer[bufPtr], 2);
	 if (a < 0)
		 {
		 if (~a+1 >= 20)
			{
			 checkFunction(a);
			 param[c] = (char *)calloc(PARAMLEN,1);
			 mystrcpy(param[c],Function[~a+1].name);
			 b = Function[~a+1].argMini;
			 if (b > 0)
				{
				iterNum = 0;
				temp =decompFunction(b,bufPtr);
				mystrcat(param[c],temp);
				temp=my_free(temp);
				if (iterNum >= MAXIT) bufPtr = 0;
				}
			 else
				mystrcat(param[c],")");
			 }
		 else
			{
			 param[c] = (char *)calloc(PARAMLEN,1);
			 iterNum = 0;
			 temp =decompOperator(2,bufPtr,~a+1,0);
			 mystrcpy(param[c],temp);
			 temp=my_free(temp);
			 if (iterNum >= MAXIT) bufPtr = 0;
			 }
		 }
	 else
		 {
		 memcpy(&a,&buffer[bufPtr], 2);
		 if (a == 0) bufPtr -=2;
		 memcpy(&a,&buffer[bufPtr], 2);

		 if (pass == 2 && variable[a].isConst == 1)
			{
			temp = varContents(a);
			param[c] = (char *)calloc(PARAMLEN,1);
			mystrcpy(param[c], temp);
			temp=my_free(temp);
			}
		 else
			{
			if (variable[a].Type == 0x0F)
				{
				if (variable[a].isConst != 2) variable[a].isConst = 0;
				param[c] = (char *)calloc(PARAMLEN,1);
				temp2 = (char *)calloc(256,1);
				sprintf(temp2,"FUNCTION%03d(",variable[a].index);
				mystrcpy(param[c],temp2);
				temp2=my_free(temp2);
				memcpy(&b,variable[a].data,2);
				b &= 0xFF;
				if (b > 0)
					{
					iterNum = 0;
					temp =decompFunction(b,bufPtr);
					mystrcat(param[c],temp);
					temp=my_free(temp);
					if (iterNum >= MAXIT) bufPtr = 0;
					}
				else
					mystrcat(param[c],")");

				}
			else
				{
                varFlag = 0;
				if (variable[a].nDim > 0)
					{
					param[c] = (char *)calloc(PARAMLEN,1);
					if (variable[a].isConst != 2) variable[a].isConst = 0;
					temp2 = toVar(a);
					mystrcpy(param[c],temp2);
					temp2=my_free(temp2);
					b = variable[a].nDim;
					if ((s == 0x7F && c == argNum -1) || (s == 0x8E))
						param[c][strlen(param[c])-1] = 0;
					else
						{
						if (b > 0)
							{
							iterNum = 0;
							temp = decompFunction(b,bufPtr);
							mystrcat(param[c],temp);
							temp=my_free(temp);
							if (iterNum >= MAXIT) bufPtr = 0;
							}
						else
							mystrcat(param[c],")");
						}
					}
				else
					{
					param[c] = (char *)calloc(PARAMLEN,1);
					if (variable[a].function != 0)
						{
						temp2 = (char *)calloc(256,1);
						sprintf(temp2,"FUNCTION%03d",variable[variable[a].function].index);
						mystrcpy(param[c],temp2);
						temp2=my_free(temp2);
						}
					else
						{
						temp2 = toVar(a);
						mystrcpy(param[c],temp2);
						temp2=my_free(temp2);

	                    if (toUnConst & (int)pow(2,argNum - c - 1))
	                    	{
        	       	        if (variable[a].isConst == 1)
								variable[a].isConst = 0;
							}
                        }
					}
				}
			}
		 }
     if (varFlag && pass == 2)
     	{
	 	compilerError++;
        writeBug=1;
        }
	 bufPtr -=2;
	 if (c != 0 && type != 8)
		mystrcat(param[c],", ");
	 if (bufPtr < 0) break;
	 }
return c;
}

void stuffBuffer(long& bufPtr, signed int w, char* buffer)
{

if (bufPtr < 0)
    errorMessage("\nFATAL ERROR 4: Bad buffer init\n");

if (bufPtr > SIZE-16)
    errorMessage(fullBuffer);

memcpy(&buffer[bufPtr], &w, 2);
bufPtr+=2;
}

void decryptXor(char *buffer, unsigned int len)
{
unsigned int i;
unsigned char c;
unsigned int a;
char xor[17] = {
    0x8C,0x53,0xB8,0xA7,0x9E,0x0F,0x0A,0xCB,0x28,0x62,0x2D,0x50,0x7E,0x05,
    0x3D,0x4E,0x35};

    a = len;
    c = 0;
    for (i = 0; i<len;i++)
    	{
        if (c > 16)
        	c = 0;
        buffer[i] = buffer[i] ^ (xor[c] + (a & 0xFF));
        c++;
        a--;
        }

}

void redecrypt(char *buffer, char *buffer2, unsigned int len, unsigned int reallen)
{
asm		xor	dx,dx			// Zero register
asm		xor	cx,cx			// Zero register
asm		jmp	loc_341
loc_335:
asm		les	bx,buffer		// Load 32 bit ptr
asm		add	bx,dx
asm		mov	al,es:[bx]
asm		les	bx,buffer2	// Load 32 bit ptr
asm		add	bx,cx
asm		mov	es:[bx],al
asm		inc	dx
asm		inc	cx
asm		les	bx,buffer	// Load 32 bit ptr
asm		add	bx,dx
asm		mov	al,es:[bx]
asm		les	bx,buffer2	// Load 32 bit ptr
asm		add	bx,cx
asm		mov	es:[bx],al
asm		inc	dx
asm		inc	cx
asm		mov	ax,cx
asm		dec	ax
asm		les	bx,buffer2	// Load 32 bit ptr
asm		add	bx,ax
asm		cmp	byte ptr es:[bx],0
asm		jne	loc_338			    // Jump if not equal
asm		jmp	short loc_337
loc_336:
asm		les	bx,buffer2	// Load 32 bit ptr
asm		add	bx,cx
asm		mov	byte ptr es:[bx],0
asm		inc	cx
asm		les	bx,buffer	// Load 32 bit ptr
asm		add	bx,dx
asm		dec	byte ptr es:[bx]
loc_337:
asm		les	bx,buffer	// Load 32 bit ptr
asm		add	bx,dx
asm		cmp	byte ptr es:[bx],1
asm		ja	loc_336		     	// Jump if above
asm		inc	dx
asm		jmp	short loc_341
loc_338:
asm		les	bx,buffer	// Load 32 bit ptr
asm		add	bx,dx
asm		cmp	byte ptr es:[bx],0
asm		jne	loc_341				// Jump if not equal
asm		les	bx,buffer2	// Load 32 bit ptr
asm		add	bx,cx
asm		mov	byte ptr es:[bx],0
asm		inc	dx
asm		inc	cx
asm		jmp	short loc_340
loc_339:
asm		les	bx,buffer2	// Load 32 bit ptr
asm		add	bx,cx
asm		mov	byte ptr es:[bx],0
asm		inc	cx
asm		les	bx,buffer	// Load 32 bit ptr
asm		add	bx,dx
asm		dec	byte ptr es:[bx]
loc_340:
asm		les	bx,buffer	// Load 32 bit ptr
asm		add	bx,dx
asm		cmp	byte ptr es:[bx],1
asm		ja	loc_339				// Jump if above
asm		inc	dx
loc_341:
asm		cmp	dx,len
asm		jae	loc_342				// Jump if above or =
asm		cmp	cx,reallen
asm		jae	loc_342				// Jump if above or =
asm		jmp	loc_335
loc_342:
}


void decrypt(char *buffer, unsigned int len)
{

if (len == 1)
	{
	buffer[0]=0;
	return;
	}

unsigned int wlen = len;
unsigned int parts = 1 + (unsigned int)len/2047;
unsigned int save;
unsigned int len2;
save = 0;
unsigned int ref=0;
unsigned int lastoff=0;
unsigned char lastbyte=1;
unsigned int dec=0;
unsigned int a;

char *startpointer;

/*if (xor17)
    {
    startpointer = buffer;
	for (a=0;a<parts;a++)
		{
        wlen = len - ref;
        if (wlen > 0x7FF)
        	wlen = 0x7FF;
		decryptXor(startpointer, wlen);
        startpointer += 0x7FF;
        ref += 0x7FF;
        }
    }

wlen = len;*/

for (a=0;a<parts;a++)
	{
//	if (!xor17)
		if (lastbyte == 0) dec++;

	ref = a * 2047;// + a/2;

	wlen -= dec;

	len = wlen - ref;

	if (len > 2047) len = 2047;

	if (lastoff == 0)
		startpointer = buffer;
	else
		startpointer = (char *)MK_FP(FP_SEG(startpointer), lastoff+=dec);

	dec=0;

if (xor17)
	decryptXor(startpointer, len);


	len2 = len >> 1;

asm		push ds
asm		push es

asm		cld

asm 	mov bx, 0xDB24       // valeur de reference

asm		mov dx, len2          // dx = longueur a decrypter / 2

asm		lds si, startpointer       // pointer sur le word suivant
asm		les di, startpointer

	dcd:

asm		lodsw

asm		mov save, ax        // sauver ax

asm		mov cl, bl
asm		add cl, dl

asm		ror ax, cl
asm		xor al, dl
asm		xor ah, dl
asm		xor ax, bx

asm		stosw

asm		mov bx, save
asm		dec dx
asm		js sdb

asm		cmp dx, 0
asm		jne dcd

	sdb:

asm		test len, 1
asm		je nof

asm		lodsb
asm		xor al, bl
asm		ror al, cl
asm		stosb

	nof:

asm		mov lastoff, di
asm		mov lastbyte, al
asm		pop es
asm		pop ds

	}
}



void main(int argc, char *argv[])
{
    Fortify_EnterScope();

 char pplxVer[] = "2.OO";

 char drive[MAXDRIVE];
 char dir[MAXDIR];
 char file[MAXFILE];
 char ext[MAXEXT];
 char c;
 char l1,l2;
 char ver[6];

 signed int a,b,d,e,f,l,lc,v,cnt,tc;
 long codeSize;
 unsigned int prev,realoctet;
 long filesize;
 long codeStart;
 long codepos;
 long ligne;
 int percent, x, y;
 float f_a, f_b;
 int concat;
 int previous;
 long bufPtr;
 long bufPtr2;
 signed int w1, w2;
 long save;
 struct ffblk ffblk;
 int done;
 int unknownStat;
 int excludedProc;
 int excludedFunc;
 int previousPercent=-1;
 int removeGoto;
 long offSave;

for (a=2;a<=argc-1;a++)
	{
#ifdef IDE
	if (!strcmp(strupr(argv[a]),"/DEBUG"))
		debug = 1;
	if (!strcmp(strupr(argv[a]),"/D"))
		debug = 1;
#endif
	if (!strcmp(strupr(argv[a]),"/N") || !strcmp(strupr(argv[a]),"/NOANALYSIS") || !strcmp(strupr(argv[a]),"/NOA"))
		noanalysis = 1;
	if (!strcmp(strupr(argv[a]),"/L") || !strcmp(strupr(argv[a]),"/LETPPU"))
		leavePPU = 1;
	if (!strcmp(strupr(argv[a]),"/U") || !strcmp(strupr(argv[a]),"/UNCRYPT"))
		onlyPPU = 1;
	if (!strcmp(strupr(argv[a]),"/F") || !strcmp(strupr(argv[a]),"/FLAT"))
		noPost = 1;
    if (!strncmp(strupr(argv[a]), "/MAXELSE=", 8))
        maxElse = atoi(&argv[a][9]);
	}

cout << "PCBoard Programming Language eXtractor "<< pplxVer << "\n";
cout << "(c)1996 - Lone Runner / AEGiS CoRP'96\n\n";

if (argc < 2)
	{
	cout << "PPLX FILENAME[.PPE] [/N] [/L] [/U] [/F] [/MAXELSE=x]\n\n";
    cout << "/N          Disable heuristic Analysis\n";
    cout << "/L          Leave uncrypted .PPU file\n";
    cout << "/U          Only uncrypt PPE to PPU\n";
    cout << "/F          Flat decompilation (no postprocessing)\n";
    cout << "/MAXELSE=x  Set max gap for Else statements (default=no limit)\n";
	exit(1);
	}

fnsplit(argv[1],drive,dir,file,ext);
sprintf(filenameSource,"%s%s%s",strupr(drive),strupr(dir),strupr(file));
if (strcmp(ext,""))
	strcat(filenameSource, strupr(ext));
else
	strcat(filenameSource,".PPE");

cursorOff();
atexit(cursorOn);

done = findfirst(filenameSource,&ffblk,0);
while (!done)
{

fileNum++;

for (a=0;a<227;a++)
	Statement[a].nUsed = 0;

for (a=0;a<287;a++)
	Function[a].nUsed = 0;

for (a=0;a<20;a++)
	flag[a]=0;

for (a=0;a<18;a++)
	index[a]=0;

a=0;
gotoIndex=0;
procIndex=0;
error=0;
nVars=0;
iterNum=0;
warning=0;
compilerError=0;
postError=0;
pIndex=0;
concat=0;
previous=0;
unknownStat=0;
excludedProc=0;
excludedFunc=0;
antiDstripped=0;

randomize();
ver[4]=0;



buffer = (char *)calloc(4096,1);
buffer2 = (char *)calloc(4096,1);

strcpy(originalName,ffblk.ff_name);
strcpy(filenameSource,ffblk.ff_name);

fnsplit(filenameSource,drive,dir,file,ext);

_in = _fopenread(filenameSource, _FILE_READBIN);
/*if ((in = fopen(filenameSource, "rb")) == NULL)
{
   cout << "Cannot open " << filenameSource << "\n";
   exit(1);
}*/

if (!onlyPPU)
	cout << "Decompiling " << originalName << "...\n";
else
	cout << "Decrypting " << originalName << "...\n";

if (!onlyPPU)
	{
    cout << "Analysis ";
	if (!noanalysis)
		cout << "ON";
	else
		cout << "OFF";
    cout << " - Postprocessing ";
	if (!noPost)
		cout << "ON\n";
	else
		cout << "OFF\n";
    }

strcpy(filename, strupr(file));
strcat(filename, ".PPU");

temp = (char*)calloc(45,1);
//fread(temp,41,1,in);
_fread(temp,41,1,_in);
if (strncmp(temp,"PCBoard Programming Language Executable  ",41))
	{
	cout << "FATAL ERROR 2: Source file " << filenameSource << " is not a valid PPE!\n";
	fcloseall();
	exit(-1);
	}
//fseek(in, 41, SEEK_SET);
_fseek(_in, 41, SEEK_SET);
//fread(&c,1,1,in);
_fread(&c,1,1,_in);
//fseek(in, 41, SEEK_SET);
_fseek(_in, 41, SEEK_SET);
//fread(&ver, 4,1,in);
_fread(&ver, 4,1,_in);
for (a=0;a<5;a++)
	if (ver[a] == '0') ver[a] = 'O';

temp=my_free(temp);

if (c > '3')
    errorMessage("Sorry, PPLX only decompile/decrypt PPE's up to v3.x\n");

if (c < '3')
	{
	printf("Format : %s (Plain PPE)\n",ver);
	format = c-'0';
	if (onlyPPU)
		cout << "Cannot decrypt a PPE " << ver << " !\n";
	}

if (c == '3')
	{

	if (ver[2] > '3' && ver[2] != 'O')
    	printf("PPLC v%s detected, PPLX may not know some codes...\n",ver);

    if (ver[2] >= '3' && ver[2] != 'O')
    	xor17 = 1;
    else
    	xor17 = 0;

	printf("Format : %s (Encryption type %s)\n",ver, (xor17) ? "II" : "I");

/*	if ((out = fopen(filename, "wb")) == NULL)
	{
	   cout << "Cannot open " << filename << "\n";
	   exit(1);
	}*/
	if ((out = fopen(filename, "wb")) == NULL)
		{
	    cout << errDisk;
	    fcloseall();
	    exit(-1);
	    }
    //_out = _fopenwrite(filename, _FILE_WRITEBIN);

//	fseek(in, 0, SEEK_END);
	_fseek(_in, 0, SEEK_END);
//	filesize = ftell(in);
	filesize = _ftell(_in);

//	fseek(in, 0x30, SEEK_SET);
	_fseek(_in, 0x30, SEEK_SET);

//	fwrite("PCBoard Programming Language Executable  2.00\x0D\x0A\x1A", 48, 1, out);
	fwrite("PCBoard Programming Language Executable  2.00\x0D\x0A\x1A", 48, 1, out);

//	fread(&a, 2, 1, in);
	_fread(&a, 2, 1, _in);
//	fwrite(&a, 2, 1, out);
	fwrite(&a, 2, 1, out);

	if (a != 0)
		{

		 for (b=0;b<a;b++)
			 {
//			 fread(buffer, 0x0B, 1, in);
			 _fread(buffer, 0x0B, 1, _in);
			 decrypt(buffer, 0x0B);
//			 fwrite(buffer, 0x0B, 1, out);
			 fwrite(buffer, 0x0B, 1, out);
			 l1 = buffer[9];
			 l2 = buffer[10];
			 if (l1 != 7)
				 {
//				 fread(buffer, 0x0C, 1, in);
				 _fread(buffer, 0x0C, 1, _in);
				 decrypt(buffer, 0x0C);
//				 fwrite(buffer, 0x0C, 1, out);
				 fwrite(buffer, 0x0C, 1, out);
				 }
			 else
				 {
//				 fread(&l, 2, 1, in);
				 _fread(&l, 2, 1, _in);
//				 fwrite(&l, 2, 1, out);
				 fwrite(&l, 2, 1, out);

//				 fread(buffer, l, 1, in);
				 _fread(buffer, l, 1, _in);
				 decrypt(buffer, l);
//				 fwrite(buffer, l, 1, out);
				 fwrite(buffer, l, 1, out);
				 }
			 }
		 }

	buffer=my_free(buffer);
	buffer2=my_free(buffer2);

//	codepos = ftell(in);
	codepos = _ftell(_in);
	codeSize = filesize-codepos-2;

//	fread(&realoctet, 2, 1, in);
	_fread(&realoctet, 2, 1, _in);
//	fwrite(&realoctet, 2, 1, out);
	fwrite(&realoctet, 2, 1, out);

	buffer = (char *)calloc(codeSize+1,1);

//	fread(buffer, codeSize, 1, in);
	_fread(buffer, codeSize, 1, _in);
	decrypt(buffer, codeSize);

	if (realoctet != codeSize)
		{
		buffer2 = (char *)calloc(realoctet+1,1);
		redecrypt(buffer, buffer2, codeSize, realoctet);
//		fwrite(buffer2, realoctet, 1, out);
		fwrite(buffer2, realoctet, 1, out);
		buffer2=my_free(buffer2);
		}
	else
//		fwrite(buffer, realoctet, 1, out);
		fwrite(buffer, realoctet, 1, out);

	buffer=my_free(buffer);
//	fclose(out);
	fclose(out);

	strcpy(filenameSource,filename);
	format = 3;
	if (onlyPPU)
		cout << originalName << " decrypted to " << filename << "\n";
	}

//fclose(in);
_fclose(_in);

if (onlyPPU)
   {
   done = findnext(&ffblk);
   if (!done) cout << "\n\n";
   continue;
   }

/*if ((in = fopen(filenameSource, "rb")) == NULL)
{
   cout << "Cannot open " << filename << "\n";
   exit(1);
}*/
_in = _fopenread(filenameSource, _FILE_READBIN);

_fseek(_in, 0, SEEK_END);
filesize = _ftell(_in);

strcpy(filename, file);
strcat(filename, ".PPX");

//_out = _fopenwrite(filename, _FILE_WRITETXT);
if ((out = fopen(filename, "wt")) == NULL)
	{
    cout << errDisk;
    fcloseall();
    exit(-1);
    }
/*if ((out = fopen(filename, "wt")) == NULL)
{
   cout << "Cannot open " << filename << "\n";
   exit(1);
}*/

cout << "Decompiling variables...\n";
x = wherex();
y = wherey();

if (buffer != NULL)
	buffer=my_free(buffer);
if (buffer2 != NULL)
	buffer2=my_free(buffer2);

buffer = (char *)calloc(SIZE,1);
buffer2 = (char *)calloc(SIZE,1);

_fseek(_in, 0x30, SEEK_SET);

_fread(&a, 2, 1, _in);

variable = (varRecord *) calloc(sizeof(varRecord)* (a+1),1);
nVars = a;
totalVar = a;

if (a != 0)
	{
	for (b=0;b<a;b++)
		{
		_fread(&varDec, sizeof(varDec), 1, _in);
		variable[varDec.varNumber].ID = varDec.varNumber;
		variable[varDec.varNumber].Type = varDec.varType & 0xFF;
		if ((variable[varDec.varNumber].Type == 0x0F) || (variable[varDec.varNumber].Type == 0x10))
			variable[varDec.varNumber].isConst = 0;
		else
			variable[varDec.varNumber].isConst = 1;
		variable[varDec.varNumber].nDim = varDec.nDim;
        if (variable[varDec.varNumber].nDim > 3 || variable[varDec.varNumber].nDim < 0) // PPP FUCKED! :)
        	{
        	variable[varDec.varNumber].nDim = 0;
		    antiDstripped++;
            }
		variable[varDec.varNumber].dim[0] = varDec.dim1;
		variable[varDec.varNumber].dim[1] = varDec.dim2;
		variable[varDec.varNumber].dim[2] = varDec.dim3;

		if ((varDec.varType & 0xFF) == 7)
			{
			_fread(&l, 2, 1, _in);
			memcpy(&variable[varDec.varNumber].data[2],&l,2);
			temp = (char *)calloc(l+1,1);
			_fread(temp, l, 1, _in);
			memcpy(&variable[varDec.varNumber].data[4],&temp,4);
			}
		else
			{
			if (format > 1)
				{
				_fread(&varDecNum, sizeof(varDecNum), 1, _in);
				memcpy(variable[varDec.varNumber].data, &varDecNum.constVal, 8);
				}
			else
				{
				_fread(&varDecNum1, sizeof(varDecNum1), 1, _in);
				memcpy(variable[varDec.varNumber].data, &varDecNum1.constVal, 4);
				}

            if (variable[varDec.varNumber].Type == 0x10 || variable[varDec.varNumber].Type == 0x0F)
				{
				memcpy(&e, &variable[varDec.varNumber].data[2],2);
				procTable[procIndex] = e;
				procIndex++;
                }

			}
		}
	}

if (c < '3')
	{
	if (nVars >= 17)
		if (variable[1].Type == 0 &&
			variable[2].Type == 0 &&
			variable[3].Type == 0 &&
			variable[4].Type == 0 &&
			variable[5].Type == 2 &&
			variable[6].Type == 4 &&
			variable[7].Type == 4 &&
			variable[8].Type == 4 &&
			variable[9].Type == 7 &&
			variable[10].Type == 7 &&
			variable[11].Type == 7 &&
			variable[12].Type == 7 &&
			variable[13].Type == 7 &&
			variable[14].Type == 7 &&
			variable[15].Type == 7 &&
			variable[16].Type == 0 &&
			variable[17].Type == 0 &&
			variable[18].Type == 0 &&
			variable[19].Type == 7 &&
			variable[20].Type == 7 &&
			variable[21].Type == 7 &&
			variable[22].Type == 7 &&
			variable[23].Type == 2)
				for (a=1;a<=23;a++)
					variable[a].predef = a;
	}
else
	if (nVars >= 18)
		if (variable[1].Type == 0 &&
			variable[2].Type == 0 &&
			variable[3].Type == 0 &&
			variable[4].Type == 0 &&
			variable[5].Type == 2 &&
			variable[6].Type == 4 &&
			variable[7].Type == 4 &&
			variable[8].Type == 4 &&
			variable[9].Type == 7 &&
			variable[10].Type == 7 &&
			variable[11].Type == 7 &&
			variable[12].Type == 7 &&
			variable[13].Type == 7 &&
			variable[14].Type == 7 &&
			variable[15].Type == 7 &&
			variable[16].Type == 0 &&
			variable[17].Type == 0 &&
			variable[18].Type == 0 &&
			variable[19].Type == 7 &&
			variable[20].Type == 7 &&
			variable[21].Type == 7 &&
			variable[22].Type == 7 &&
			variable[23].Type == 2 &&
			variable[24].Type == 4)
				for (a=1;a<=24;a++)
					variable[a].predef = a;


pass=1;
save = _ftell(_in);

gotoxy(x,y-1);
cout << blankLine;
gotoxy(x,y-1);
cout << "Decompiling code...\n";

passLoop:
removeGoto=0;
/*if (debug)
	if (pass == 1)
		cout << "\nPass 1...";
	else
		cout << "\nPass 2...";*/

if (pass == 2)
	{
		   fputs(remLine,out);
		   fputs(";                                                   .ss.\n",out);
		   fputs(";                                                   `ýý'\n",out);
		   fputs(";             .,sS$Ss,,s$  .,sS$$$Ss.  .,sS$Ss,,s$ .ss.  .sSs.\n",out);
		   fputs(";           .d$$ý^øý$$$$'.d$Pýø^^ý$P'.d$$ý^øý$$$$'.$$$' .$$$ýSb,.\n",out);
		   fputs(";           $$$'   .$$$' $$$ýS‡sæý' .$$$'   .$$$'.$$$' .$$$'  `$$b.\n",out);
		   fputs(";           $$$b,,d$$$' ,$$$b,....,s$$$$b,,d$$$'.$$$;.,$$$'    ;$$$\n",out);
		   fputs(";           `ýS$$SýýS$$SýøýS$$$$Sýø""øýS$$$$$$',$$SýøýS$S'.sS$$$Pý'\n",out);
		   fputs(";                                    .sSýø$$$ýýø\"'       dýø""'\n",out);
		   fputs(";                                  .$$ý  .$$'\n",out);
		   fputs(";                                  $$$.,d$$'\n",out);
		   fputs(";                                  `ýS$$Sý'\n",out);
		   fputs(remLine,out);
/*		   fputs(";        ___________      _______________________        _____________         \n",out);
		   fputs(";[=======\\          \\====/          /           /_____  /            /=======] \n",out);
		   fputs("; ::::::::\\  ______  \\::/  \\_____  /  _______  /______)/  \\_______  /::::::::  \n",out);
		   fputs("; ::kL!:::_\\/    _/   \\/   ___)__\\/   \\      \\/        \\_________ \\/:::::::::  \n",out);
		   fputs("; ::::::::\\     __     \\_  \\      \\_   \\_     \\_        \\_      /  \\_::::::::  \n",out);
		   fputs(";[=========\\_____/______/__________/___________/_________/__________/========] \n",out);
		   fputs(";                                                                              \n",out);
		   fputs(";                      C          O          R          P                      \n",out);
		   fputs(";------------------------------------------------------------------------------\n",out);*/
	fprintf(out, "; P.P.L.X. %s                          (C)1996 - Lone Runner / AEGiS CoRP'96 \n",pplxVer);
		   fputs(remLine,out);
	if (format>=3)
	fprintf(out, "; PPE %s (Encryption type %s) - Analysis ",ver, (xor17) ? "II" : "I");
		else
	fprintf(out, "; PPE %s (plain) - Analysis ",ver);

	if (!noanalysis)
	fputs("ON",out);
	else
	fputs("OFF",out);

    fputs(" - Postprocessing ", out);
    if (!noPost)
    fputs("ON\n", out);
	else
	fputs("OFF\n",out);


	fputs(remLine,out);

	qsort((void *)gotoTable, gotoIndex, sizeof(gotoTable[0]), sort_function);

	_fseek(_in, 0x30, SEEK_SET);
	_fread(&a, 2, 1, _in);
	l=0;
	if (a != 0)
		{
		fputs("\n",out);
		_fseek(_in,save,SEEK_SET);

		for (b=1;b<=a;b++)
			{
			if (variable[b].isConst != 1)
				{
				index[variable[b].Type]++;
				variable[b].index = index[variable[b].Type];
                }
            }

        for (tc=0;tc<18;tc++)
        	{

		    for (b=1;b<=a;b++)
			    {

                if (variable[b].Type != tc) continue;

			    if (!variable[b].isConst)
				    {

				    if ((variable[b].Type != 0xF) && (variable[b].Type != 0x10) && (variable[b].function == 0) && (variable[b].local == 0) && (variable[b].predef == 0))
					    {
					    if (variable[b].nDim == 0)
						    fprintf(out, "    %-9s%s%03d\n",Type[variable[b].Type], UType[variable[b].Type], variable[b].index);
					    else
						    {
						    fprintf(out, "    %-9sT%s%03d(",Type[variable[b].Type], UType[variable[b].Type], variable[b].index);
						    for (f=0;f<variable[b].nDim;f++)
							    {
							    fprintf(out,"%d",variable[b].dim[f]);
							    if (f != variable[b].nDim-1) fputs(",", out);
							    }
						    fputs(")\n", out);
						    }
					    }
				    else
					    if (variable[b].Type == 0xF || variable[b].Type == 0x10)
						    if (variable[b].Type == 0x10)
							    {
							    memcpy(&e, &variable[b].data[2],2);
							    if (e != 0)
								    {
								    fprintf(out, "    Declare  Procedure PROC%03d(", variable[b].index);

    /*								memcpy(&e, &variable[b].data[2],2);
								    procTable[procIndex] = e;
								    procIndex++;*/

								    memcpy(&v, &variable[b].data[6], 2);
                                    v &= 0xFF;

								    memcpy(&f, &variable[b].data, 2);
								    f &= 0xFF; // f = n. de params

								    memcpy(&e,&variable[b].data,2);
								    lc = (e & 0xFF00) >> 8; // lc = n. de var locales

								    memcpy(&e,&variable[b].data[4],2);
								    e += 1; // e = 1ere variable concernee

								    for (d=e,cnt=1;d<e+f;d++,cnt++)
									    {
                                        if (v & (int)pow(2,cnt-1))
										    fprintf(out,"Var %s %s%03d",Type[variable[d].Type], UType[variable[d].Type], variable[d].index);
                                        else
											fprintf(out,"%s %s%03d",Type[variable[d].Type], UType[variable[d].Type], variable[d].index);
									    if (d < e+f-1)
										    fputs(", ", out);
    //									variable[d].isConst = 0;
									    }
								    fputs(")\n", out);
								    }
							    else
                            	    excludedProc++;
							    }
						    else
							    {
							    memcpy(&e, &variable[b].data[2],2);
							    if (e != 0)
								    {
								    fprintf(out, "    Declare  Function FUNCTION%03d(", variable[b].index);

    /*								memcpy(&e, &variable[b].data[2],2);
								    procTable[procIndex] = e;
								    procIndex++;*/

								    memcpy(&f, &variable[b].data, 2);
								    f &= 0xFF; // f = n. de params

								    memcpy(&e,&variable[b].data,2);
								    lc = (e & 0xFF00) >> 8; // lc = n. de var locales + 1 (variable de retour)

								    memcpy(&e,&variable[b].data[6],2);
								    e -= f; // e = 1ere variable concernee

								    for (d=e,cnt=1;d<e+f;d++,cnt++)
									    {
									    fprintf(out,"%s %s%03d",Type[variable[d].Type], UType[variable[d].Type],variable[d].index);
									    if (d < e+f-1)
										    fputs(", ", out);
    //									variable[d].isConst = 0;
									    }
								    d = e+f;
								    fputs(")", out);
								    fprintf(out," %s\n",Type[variable[d].Type]);
								    variable[d].function = b;
								    }
							    else
                            	    excludedFunc++;
							    }
				    }
			    }
    		}
		}
		fputs("\n",out);
	}
else
	{
	for (b=1;b<=a;b++)
		{
		if (variable[b].Type == 0xF || variable[b].Type == 0x10)
			{
			if (variable[b].Type == 0x10)
				{
				memcpy(&e, &variable[b].data[2],2);
				if (e != 0)
					{
					memcpy(&f, &variable[b].data, 2);
					f &= 0xFF; // f = n. de params

					memcpy(&e,&variable[b].data,2);
					lc = (e & 0xFF00) >> 8; // lc = n. de var locales

					memcpy(&e,&variable[b].data[4],2);
					e +=f+1; // e = 1ere variable concernee

					for (d=e;d<e+lc;d++)
						variable[d].local = 1;

					}
				}
			else
				{
				memcpy(&e, &variable[b].data[2],2);
				if (e != 0)
					{
					memcpy(&f, &variable[b].data, 2);
					f &= 0xFF; // f = n. de params

					memcpy(&e,&variable[b].data,2);
					lc = (e & 0xFF00) >> 8; // lc = n. de var locales + 1 (variable de retour)

					memcpy(&e,&variable[b].data[6],2);
					e += 1; // e = 1ere variable concernee

					for (d=e;d<e+lc;d++)
						variable[d].local = 1;

					}
				}
			}
		}
	}



_fread(&a, 2, 1, _in);

if (pass == 2 && a > 0)
	{
	fputs(remLine,out);
	fputs("\n",out);
	}

codeStart = _ftell(_in);
char argType[12];
ligne = 0;
previous=0;
concat=0;
s=0;

for (;;)
	{
	bufPtr = 0;						// Initialiser buffer
    if (!concat) writeBug=0;

	if (((filesize - codeStart) * 2) != 0)
		{
		f_a = (_ftell(_in) - codeStart);
		f_b = (filesize - codeStart);
		percent = f_a / f_b * 50 + 50*(pass-1);
        if (percent != previousPercent)
        	{
            for (b=0;b<percent>>2;b++)
        	    cout << "±";
            for (;b<25;b++)
        	    cout << "°";
		    printf(" %d%% ",percent);
		    gotoxy(x,y);
            previousPercent = percent;
            }
		}

	previous = s;

	if (_ftell(_in) >= filesize) break;

	a = _ftell(_in) - codeStart;

	if (procInTable(a) && a != 0)
		{
        previous=0;
		l = getProcIndex(a);

        if (variable[l].Type == 0x10)
			{
            if (pass == 2)
            	{
			    fputs("\n", out);
				fputs(remLine,out);
				fprintf(out, "\nProcedure PROC%03d(", variable[l].index);
                }

			memcpy(&v, &variable[l].data[6], 2);
            v &= 0xFF;
			memcpy(&e, &variable[l].data[4],2);
			memcpy(&l, &variable[l].data,2);
			lc = (l & 0xFF00) >> 8; // n. locals
			l &= 0xFF; // n. params
			e +=1;
			for (d=e,cnt=1;d<e+l;d++,cnt++)
				{
	            if (pass == 2)
                	{
                    if (v & (int)pow(2,cnt)/2)
						fprintf(out,"Var %s %s%03d",Type[variable[d].Type], UType[variable[d].Type],variable[d].index);
                    else
						fprintf(out,"%s %s%03d",Type[variable[d].Type], UType[variable[d].Type],variable[d].index);
					if (d < e+l-1)
					    fputs(", ", out);
                    }
                else
					variable[d].isConst = 2;
				}
            if (pass == 2)
			    fputs(")\n\n", out);

			if (lc > 0)
				{
				e+=l;
				l=0;
				for (d=e;d<e+lc;d++)
					{
					if (variable[d].isConst == 1) continue;
					if (d > nVars) continue;
					l++;
					if (variable[d].nDim == 0)
						fprintf(out, "    %-9s%s%03d\n",Type[variable[d].Type], UType[variable[d].Type], variable[d].index);
					else
						{
						fprintf(out, "    %-9sT%s%03d(",Type[variable[d].Type], UType[variable[d].Type], variable[d].index);
						for (f=0;f<variable[d].nDim;f++)
						fprintf(out,"%d",variable[d].dim[f]);
					    fputs(")\n", out);
						}
					}
				if (l != 0)
				    fputs("\n", out);
				}
			}
		else
			{

            if (pass == 2)
            	{
			    fputs("\n", out);
				fputs(remLine, out);
				fprintf(out, "\nFunction FUNCTION%03d(", variable[l].index);
                }

			memcpy(&e, &variable[l].data[6],2);
			memcpy(&l, &variable[l].data,2);
			lc = (l & 0xFF00) >> 8;
			l &= 0xFF;
			e -= l;
			for (d=e,cnt=1;d<e+l;d++,cnt++)
				{
	            if (pass == 2)
					{
					fprintf(out,"%s %s%03d",Type[variable[d].Type], UType[variable[d].Type],variable[d].index);
					if (d < e+l-1)
					    fputs(", ", out);
                    }
                else
                    variable[d].isConst = 2;
				}
			d = e+l;
            if (pass == 2)
			    fprintf(out,") %s\n\n",Type[variable[d].Type]);

			if (lc > 0)
				{
				e += l+1;
				l = 0;
				for (d=e;d<e+lc;d++)
					{
					if (variable[d].isConst == 1) continue;
                    if (d > nVars) continue;
					l++;
					if (variable[d].nDim == 0)
						fprintf(out, "    %-9s%s%03d\n",Type[variable[d].Type], UType[variable[d].Type], variable[d].index);
					else
						{
						fprintf(out, "    %-9sT%s%03d(",Type[variable[d].Type], UType[variable[d].Type], variable[d].index);
						for (f=0;f<variable[d].nDim;f++)
						fprintf(out,"%d",variable[d].dim[f]);
					    fputs(")\n", out);
						}
					}
				if (l != 0)
				    fputs("\n", out);
				}
			}
		}

	if (pass == 2 && gotoInTable(a))
		{
        previous=0;
		sprintf(buffer2, ":LABEL%03d",getGotoIndex(a));
		fprintf(out,"%s\n", buffer2);
		}

	ligne++;
    toUnConst=0;

	_fread(&s, 2, 1, _in);
    if (removeGoto > 0)
		removeGoto--;
	decal = _ftell(_in);
	if (debug)
		printf("\nLine %d, offset 0x%X - ", ligne, decal);

	if (pass == 2)
		Statement[s].nUsed++;


	if (!noanalysis)
		if (pass == 2)
			switch (s)
				{
				case 0xC:  // confflag
				case 0xD:  // confunflag
					flag[0] = 1;
					break;
				case 0x1C: // putuser
					flag[1] = 1;
					break;
				case 0x89: // getaltuser
					flag[2] = 1;
					break;
				case 0x1F: // deluser
					flag[3] = 1;
					break;
				case 0x20: // adjtime
					flag[4] = 1;
					break;
				case 0x1A: // hangup
				case 0x2D: // dtroff
					flag[5] = 1;
					break;
				case 0x31: // sendmodem
				case 0x66: // mprint
				case 0x67: // mprintln
					flag[6] = 1;
					break;
				case 0x38: // shell
					flag[7] = 1;
					break;
				case 0x40: // call
					flag[8] = 1;
					break;
				case 0x50: // dointr
					flag[9] = 1;
					break;
				case 0x53: // poke
				case 0x54: // pokew
				case 0x6A: // pokedw
					flag[10] = 1;
					break;
				case 0x5C: // newpwd
					flag[11] = 1;
					break;
				case 0x7C: // adjbytes
				case 0x8A: // adjDbytes
				case 0x8B: // adjTbytes
				case 0x8C: // adjTfiles
					flag[12] = 1;
					break;
				case 0x86: // flag
					flag[13] = 1;
					break;
				}


	argNum = Statement[s].argMini;

	if ((((!strcmp(Statement[s].name,"")) || (s > HiStatement)) && s != 0xA8) && pass == 1)
		{
       	unknownStat++;
		warning++;
		continue;
		}

	switch (concat)
		{
		case 0:
			strcpy(buffer2, "    ");
			break;
		case -1:
			strcpy(buffer2, "    ");
			concat =0;
			break;
		case 1:
			concat = -1;
			break;
		}

	strcat(buffer2, Statement[s].name);

	if (s == 0xA8)
		{
		_fread(&w1, 2, 1, _in);
		_fread(&w2, 2, 1, _in);
		sprintf(buffer2+strlen(buffer2),"PROC%03d(",variable[w1].index);
		memcpy(&argNum,&variable[w1].data,2);
		argNum &= 0xFF;
		Statement[s].argMaxi = argNum;
        memcpy(&toUnConst, &variable[w1].data[6], 2);
        toUnConst &= 0xFF;
		}

	if ((s == 0xA9) || (s == 0xAB))
		{
		sprintf(buffer2, "\n%s\n", Statement[s].name);
		}

	if (s == 1 && _ftell(_in) == filesize && concat != -1)
		{
		if (pass == 2) Statement[s].nUsed--;
		break;
		}

	if (s == 0x0B)
		strcat(buffer2,"("); // -----------+ !(

	if (s == 7 || s == 0x29)
		{
		_fread(&a, 2, 1, _in);

        if (removeGoto == 1 && s == 7)
           	continue;

		if (pass == 1 && !gotoInTable(a))
			{
			sprintf(buffer2+strlen(buffer2), "%04X",a);
			gotoTable[gotoIndex] = a;
			gotoIndex++;
			}

		if (pass == 2)
			{
			sprintf(buffer2+strlen(buffer2), "LABEL%03d",getGotoIndex(a));

			fprintf(out,"%s\n", buffer2);
			}
		continue;
		}

	if (Statement[s].argMaxi != argNum)
		_fread(&argNum, 2, 1, _in);

	if (argNum != 0)
		{

		for (a=0;a<12;a++)
			argType[a] = 0;

		switch(Statement[s].argType)
			{
			case 0x075F:
            case 0x08B7:
				argType[0] = 1;
				break;

			case 0x075B:
				argType[0] = 1;
				argType[1] = 1;
				break;

			case 0x07B5:
				argType[1] = 1;
				break;

			case 0x07E5:
				argType[2] = 1;
				break;

			case 0x078C:
				argType[0] = 1;
				argType[1] = 1;
				break;

			case 0x0836:
				argType[0] = 2;
				break;

			case 0x088C:
				argType[0] = 2;
				argType[1] = 2;
				break;

			case 0x2585:
				argType[3] = 2;
				break;

			default:
				break;
			}

		d=0;
		e=0;

		for (;;)
			{
			e++;

			if (d == argNum) break;

/*			if (debug)
				printf("\nd = %d, argNum = %d - ",d,argNum);*/

			if (argType[d] == 1)
				{
				getPair(w1, w2);
				if (variable[w1].nDim > 0)
					{
					_fseek(_in,-4,SEEK_CUR);
					temp = reverseFunction(w2);
					memcpy(&buffer[bufPtr],temp,w2);
					temp=my_free(temp);
					bufPtr += w2;
					d++;
					continue;
					}
				stuffBuffer(bufPtr, w1, buffer);
				stuffBuffer(bufPtr, w2, buffer);
				d++;
				if (variable[w1].isConst != 2) variable[w1].isConst = 0;
				continue;
				}

			if (argType[d] == 2)
				{
				_fread(&w1, 2, 1, _in);
				stuffBuffer(bufPtr, w1, buffer);
				d++;
				if (d == argNum)
					{
					stuffBuffer(bufPtr, 0, buffer);
					stuffBuffer(bufPtr, 0, buffer);
					}
				continue;
				}

			boucleVar:

			if (bufPtr > SIZE-2)
			    errorMessage(fullBuffer);

			getPair(w1, w2);

			if (!isVariable(w1,w2))
				{
				stuffBuffer(bufPtr, w1, buffer);
					d++;
				if (w1 == 0)
					{
					d--;
					_fseek(_in, -2, SEEK_CUR);
//					bufPtr -=2;
					if ((w1 == 0) && (e == argNum))
						d = argNum;

					continue;
					}
				if (w1 < 0)
					{
					d--;
					_fseek(_in, -2, SEEK_CUR);

					prev=0;

					while(w1 < 0)
						{
						d++;
						checkFunction(w1);
						if (pass == 2) Function[~w1+1].nUsed++;
						d -= Function[~w1+1].argMini;
						if (prev == 0xFFF0 && prev == w1)
							{
							bufPtr -= 4;
							prev = 0;
							if (pass == 2) Function[~w1+1].nUsed--;
							}
						else
							prev = w1;
						_fread(&w1, 2, 1, _in);
						stuffBuffer(bufPtr, w1, buffer);
						}

					if (w1 > 0)
						{
						bufPtr -=2;
//                        stuffBuffer(bufPtr, 0, buffer); // ---------+!!!
						_fseek(_in, -2, SEEK_CUR);
						goto boucleVar;
						}

					if ((w1 == 0) && (e == argNum))
						d = argNum;

					continue;
					}
				if (w1 > 0)
					{
					d--;
					bufPtr -=2;
					_fseek(_in,-2,SEEK_CUR);
					goto boucleVar;
					}

				}
			else
				{
				if (variable[w1].Type == 0x0F || variable[w1].nDim > 0)
					{
					_fseek(_in,-4,SEEK_CUR);
					handlefunc:
					temp = reverseFunction(w2);
					memcpy(&buffer[bufPtr],temp,w2);
					temp=my_free(temp);
					bufPtr += w2;
					d++;
					goto boucleVar;
					}
				stuffBuffer(bufPtr, w1, buffer);
				stuffBuffer(bufPtr, w2, buffer);
				d++;
				if ((s == 8 && d == 1))
					if (variable[w1].isConst != 2) variable[w1].isConst = 0;

				goto boucleVar;
				}
			}

		lineOK:

		decompLigne(bufPtr, s);

		if (iterNum >= MAXIT) continue;

		if (s != 8)
			{
			for (a=argNum-1;a>=0;a--)
				{
			    if (s == 0xB)
			    	{
                    offSave = _ftell(_in);
					_fread(&w1, 2, 1, _in);
                    _fseek(_in, w1+codeStart-4, SEEK_SET);
					_fread(&w1, 2, 1, _in);
                    if (w1 != 7)
                    	goto nop1;
                    _fseek(_in, -2, SEEK_CUR);
                    if (_ftell(_in) == offSave+2)
                    	goto nop1;
                    strcpy(&buffer2[strlen(buffer2)-4], "While (");
                    removeGoto=3;
                    nop1:
                    _fseek(_in, offSave, SEEK_SET);
			        }
				strcat(buffer2,param[a]);
				param[a]=my_free(param[a]);
				}
			}
		else
			{
			strcpy(&buffer2[(strstr(buffer2, "Let")-buffer)],param[1]);
			strcat(buffer2," = ");
			strcat(buffer2,param[0]);
			param[0]=my_free(param[0]);
			param[1]=my_free(param[1]);
			}

		if (s == 0x0B)
			{
			_fread(&a, 2, 1,_in);
			sprintf(buffer2+strlen(buffer2),") ",a);
			concat = 1;
			continue;
			}

		}

	if (s == 0xA8)
		strcat(buffer2,")");

	if (pass == 2)
		{
		if ((((previous == 0xA9) || (previous == 0xAB)) && (s == 1)))
			Statement[s].nUsed--;
		else
			if (((previous == 1) && (s == 1)))
				Statement[s].nUsed--;
			else
                if (!writeBug)
					fprintf(out,"%s\n", buffer2);
                else
					fprintf(out,"%s ; PPLC BUG!\n", buffer2);
		}

	concat = 0;

	}

if (pass == 1)
	{
	pass = 2;
	goto passLoop;
	}

status(0,0,1);
gotoxy(x,y);

fputs("\n",out);
fputs(remLine,out);
fputs(";\n",out);
fputs("; Usage report", out);
if (!noPost)
fputs(" (before postprocessing)\n;\n", out);
else
fputs("\n;\n", out);

fputs("; þ Statements used :\n",out);
fputs(";\n",out);
for (a=0;a<=HiStatement;a++)
	if (Statement[a].nUsed && strcmp(Statement[a].name,""))
		fprintf(out,";    %-4d    %s\n",Statement[a].nUsed,Statement[a].name);
fputs(";\n",out);
fputs(";\n",out);
fputs("; þ Functions used :\n",out);
fputs(";\n",out);
for (a=0;a<=HiFunction;a++)
	if (Function[a].nUsed)
		{
		fprintf(out,";    %-4d    %s",Function[a].nUsed,Function[a].name);
		if (a > 20)
			fputs(")",out);
		fputs("\n",out);
		}
fputs(";\n",out);

/*x = wherex();
y = wherey();
cout << "                                                  ";
gotoxy(x,y);*/

if (!noanalysis)
	{
	fputs(remLine,out);
	fputs(";\n",out);
	fputs("; Analysis flags : ",out);

	b=0;
	for (a=0;a<19;a++)
		if (flag[a])
			{
			b++;
			fputc(flagL[a],out);
			}

	if (b)
		fputs("\n",out);
	else
		fputs("No flag\n",out);

	fputs(";\n",out);

	if (flag[0])
		{
		fputs("; F - Change conference flags status þ 2\n",out);
		fputs(";     This may be normal for a SELECT replacement but it may also be\n",out);
		fputs(";     a way to get access to conferences a user is not allowed to.\n",out);
		fputs(";     þ Search for : CONFFLAG, CONFUNFLAG\n",out);
		fputs(";\n",out);
		}
	if (flag[1])
		{
		fputs("; W - Write user þ 5\n",out);
		fputs(";     Program writes a user record. Although this may be normal for a\n",out);
		fputs(";     User Editor, it may also be a way to modify an account level.\n",out);
		fputs(";     þ Search for : PUTUSER\n",out);
		fputs(";\n",out);
		}
	if (flag[2])
		{
		fputs("; R - Read user þ 5\n",out);
		fputs(";     User records are read, this may signify that someone wants to get\n",out);
		fputs(";     various informations about a user (for example his password), but\n",out);
		fputs(";     this may also be normal for a program accessing user records (for\n",out);
		fputs(";     example a User Editor)\n",out);
		fputs(";     þ Search for : GETALTUSER\n",out);
		fputs(";\n",out);
		}
	if (flag[3])
		{
		fputs("; D - Delete user þ 5\n",out);
		fputs(";     Program is deleting account(s)... Check!\n",out);
		fputs(";     þ Search for : DELUSER\n",out);
		fputs(";\n",out);
		}
	if (flag[4])
		{
		fputs("; A - Adjust online time remaining þ 5\n",out);
		fputs(";     Program modify the amount of online time remaining, this may\n",out);
		fputs(";     be a way to bypass time limits\n",out);
		fputs(";     þ Search for : ADJTIME\n",out);
		fputs(";\n",out);
		}
	if (flag[5])
		{
		fputs("; B - Brute hangup þ 1\n",out);
		fputs(";     Program hangup without notification. This may be a good way to\n",out);
		fputs(";     disconnect a user, but if used randomly, may be very nasty\n",out);
		fputs(";     þ Search for : HANGUP, DTROFF\n",out);
		fputs(";\n",out);
		}
	if (flag[6])
		{
		fputs("; M - Send text to modem only þ 4\n",out);
		fputs(";     Some informations are sent only to the modem, not to the local\n",out);
		fputs(";     screen, this is a well known way to make stealth backdoors, Check!\n",out);
		fputs(";     þ Search for : SENDMODEM, MPRINT, MPRINTLN\n",out);
		fputs(";\n",out);
		}
	if (flag[7])
		{
		fputs("; S - Shell to DOS þ 5\n",out);
		fputs(";     This may be normal if the PPE need to execute an external command,\n",out);
		fputs(";     but may be actually anything... nasty (formating HD, rebooting,...)\n",out);
		fputs(";     or usefull (sorting, maintenance,...). Check!\n",out);
		fputs(";     þ Search for : SHELL\n",out);
		fputs(";\n",out);
		}
	if (flag[8])
		{
		fputs("; C - Call child PPE þ 3\n",out);
		fputs(";     This is usually normal, but may be a tricky way to launch some\n",out);
		fputs(";     sysop-only commands.\n",out);
		fputs(";     þ Search for : CALL\n",out);
		fputs(";\n",out);
		}
	if (flag[9])
		{
		fputs("; I - Interrupt call þ 5\n",out);
		fputs(";     This is rare in PPE... Although it may be a way to replace a PPE\n",out);
		fputs(";     command by its fast interrupt equivalent. Be aware that an\n",out);
		fputs(";     interrupt call may do anything... nasty (formating HD, rebooting,...)\n",out);
		fputs(";     or usefull (fast screen i/o, hardware ressource access,...). Check!\n",out);
		fputs(";     þ Search for : DOINTR\n",out);
		fputs(";\n",out);
		}
	if (flag[10])
		{
		fputs("; P - Poke in memory þ 3\n",out);
		fputs(";     This may write in some usefull informations, but it may also\n",out);
		fputs(";     crash a machine.\n",out);
		fputs(";     þ Search for : POKE, POKEW, POKEDW\n",out);
		fputs(";\n",out);
		}
	if (flag[11])
		{
		fputs("; c - Change password þ 3\n",out);
		fputs(";     Program directly changes a user's password. This may be ok for\n",out);
		fputs(";     a password history manager, but it is very suspect. Check!\n",out);
		fputs(";     þ Search for : NEWPWD\n",out);
		fputs(";\n",out);
		}
	if (flag[12])
		{
		fputs("; a - Adjust ratio þ 4\n",out);
		fputs(";     User's ratio is adjusted by changing the amount of files/bytes\n",out);
		fputs(";     uploaded. This may be normal for a user editor.\n",out);
		fputs(";     þ Search for : ADJBYTES, ADJDBYTES, ADJTBYTES, ADJTFILES\n",out);
		fputs(";\n",out);
		}
	if (flag[13])
		{
		fputs("; f - Flag files for download þ 3\n",out);
		fputs(";     This may be normal if a PPE needs to send some files, but since\n",out);
		fputs(";     this statement allows flagging of any file on the hard disk, you\n",out);
		fputs(";     have to be carefull. Check!\n",out);
		fputs(";     þ Search for : FLAG\n",out);
		fputs(";\n",out);
		}
	if (flag[14])
		{
		fputs("; d - Access PCBOARD.DAT þ 2\n",out);
		fputs(";     Program gets the full pathname to PCBOARD.DAT, this may be usefull\n",out);
		fputs(";     for many PPE so they can find various informations on the system\n",out);
		fputs(";     (system paths, max number of lines in messages, ...) but it may also\n",out);
		fputs(";     be a way to gather vital informations.\n",out);
		fputs(";     þ Search for : PCBDAT()\n",out);
		fputs(";\n",out);
		}
	if (flag[15])
		{
		fputs("; p - Peek in memory þ 2\n",out);
		fputs(";     Since a peek statement allows someone to read entire memory contents\n",out);
		fputs(";     you may check this statement, however, this is usually not a risk\n",out);
		fputs(";     þ Search for : PEEK, PEEKW, PEEKDW\n",out);
		fputs(";\n",out);
		}
	if (flag[16])
		{
		fputs("; H - Read Password or Password History þ 5\n",out);
		fputs(";     Program is reading the user's password or last password history\n",out);
		fputs(";     This may be ok for a password manager, but it is very suspect. Check!\n",out);
		fputs(";     þ Search for : U_PWDHIST, U_PWD\n",out);
		fputs(";\n",out);
        }
	if (flag[17])
		{
		fputs("; i - Sequencially read files in directory þ 3\n",out);
		fputs(";     Program is reading files in directory sequencially, maybe to get\n",out);
		fputs(";     a DIR image, but this can be to look for targets to destroy\n",out);
		fputs(";     þ Search for : FINDFIRST(), FINDNEXT()\n",out);
		fputs(";\n",out);
		}
	if (flag[18])
		{
		fputs("; s - Sysop level access þ 5\n",out);
		fputs(";     Program is reading the sysop access level, this may be normal\n",out);
		fputs(";     but still it is very suspect. It is the best way to give a user\n",out);
		fputs(";     all priviledges. Check!\n",out);
		fputs(";     þ Search for : SYSOPSEC()\n",out);
		fputs(";\n",out);
		}
	}

if (compilerError)
	{
    fputs(";\n",out);
    fputs(remLine,out);
    fputs(";\n",out);
    fputs(";     One or more PPLC bugs were found, this is not a PPLX error, but PPLX is  \n",out);
    fputs(";     reporting the error ;)  Some statements  like VAR = !!!!10, VAR = !0*!0  \n",out);
    fputs(";     or similar things are not handled  correctly by PPLC, some may use this  \n",out);
    fputs(";     to  avoid a  correct decompilation...  This doesn't mean that there  is  \n",out);
    fputs(";     actually an error, but the probability of error is high...               \n",out);
	fputs(";     þ Search for : PPLC BUG\n",out);
    fputs(";\n",out);
    }

fputs(remLine,out);
fputs(AegisDevise,out);
fputs(remLine,out);

buffer=my_free(buffer);
buffer2=my_free(buffer2);
for (a=0;a<=nVars;a++)
	if (variable[a].Type == 7)
    	{
		memcpy(&temp,&variable[a].data[4],4);
    	if (temp != NULL)
			free(temp);
        }
variable=(varRecord *)my_free(variable);
_fclose(_in);
fclose(out);

if (!noPost)
	{
	gotoxy(x,y-1);
    cout << blankLine;
	gotoxy(x,y-1);
    cout << "Postprocessing...";
	gotoxy(x,y);
	post(filename);
    }
else
	{
	cout << blankLine;
    gotoxy(x,y);
    }
gotoxy(x,y-1);
cout << blankLine;

b=0;
if (!noanalysis)
	{
	cout << "Analysis flags : ";

	b=0;
	for (a=0;a<19;a++)
		if (flag[a])
			{
			b++;
			cout << flagL[a];
			}
	if (b)
		cout << "\n";
	else
		cout << "No flag\n";
    }

if (excludedProc)
	printf("%d procedure(s) were found in code but not used.\n",excludedProc);

if (excludedFunc)
	printf("%d function(s) were found in code but not used.\n",excludedFunc);

if (unknownStat)
	printf("%d statement code(s) were unknown and ignored.\n",unknownStat);

if (antiDstripped)
	printf("%d antidecompilation system(s) were stripped.\n",antiDstripped);

if (compilerError)
	printf("%d PPLC bug(s) were detected...\n",compilerError);

if (postError)
	printf("Error(s) during postprocessing, try using PPLX /F\n");

if (unknownStat || excludedFunc || excludedProc || antiDstripped || compilerError)
	cout << "\n";

if (error != 0)
	cout << originalName << " had decompilation error(s)... " << filename << " may contain irrational code...\n";
else
	cout << originalName << " decompiled to " << filename << " !\n";

if (warning != 0)
	cout << originalName << " had warning(s)...\n";


if (format == 3 && !leavePPU)
	unlink(filenameSource);

   done = findnext(&ffblk);

   if (!done) cout << "\n\n";
}

Fortify_LeaveScope();

#pragma warn -aus
}
#pragma warn .aus



char *reverseFunction(int& count)
{

int w1,w2,s,d=0,e=0;
int argNum;
long buf2Ptr=0;
unsigned int prev;
char c;
char *localBuffer;

localBuffer = (char *)calloc(2048,1);

getPair(s, w2);

if (variable[s].Type == 0x0F)
	{
	memcpy(&argNum,variable[s].data,2);
	argNum &= 0xFF;
	}
else
	{
	if (variable[s].isConst != 2) variable[s].isConst = 0;
	argNum = variable[s].nDim;
	}


d=0;
e=0;
	for (;;)
		{
		e++;

		if (d == argNum) break;

		boucleVar2:

		if (buf2Ptr > 2046)
		    errorMessage(fullBuffer);

		getPair(w1, w2);

		if (!isVariable(w1,w2))
			{
			stuffBuffer(buf2Ptr, w1, localBuffer);
			d++;
			if (w1 == 0)
				{
				d--;
				_fseek(_in, -2, SEEK_CUR);
				buf2Ptr -=2;
				if ((w1 == 0) && (e == argNum))
                    {
					d = argNum;
                    }
				continue;
				}
			if (w1 < 0)
				{
				d--;
				_fseek(_in, -2, SEEK_CUR);
					prev=0;
					while(w1 < 0)
					{
					d++;
					checkFunction(w1);
					if (pass == 2) Function[~w1+1].nUsed++;
					d -= Function[~w1+1].argMini;
					if (prev == 0xFFF0 && prev == w1)
						{
						buf2Ptr -= 4;
						prev = 0;
						if (pass == 2) Function[~w1+1].nUsed--;
						}
					else
						prev = w1;
					_fread(&w1, 2, 1, _in);
					stuffBuffer(buf2Ptr, w1, localBuffer);
					}
					if (w1 > 0)
						{
						buf2Ptr -=2;
						_fseek(_in, -2, SEEK_CUR);
						goto boucleVar2;
						}
				buf2Ptr -= 2;
				if ((w1 == 0) && (e == argNum))
					d = argNum;
				continue;
				}
			if (w1 > 0)
				{
				d--;
				buf2Ptr -=2;
				_fseek(_in, -2, SEEK_CUR);
				goto handlefunc2;
				}
			}
		else
			{
			if (variable[w1].Type == 0x0F || variable[w1].nDim > 0)
				{
				_fseek(_in,-4,SEEK_CUR);
				handlefunc2:
				temp = reverseFunction(w2);
				memcpy(&localBuffer[buf2Ptr],temp,w2);
				temp=my_free(temp);
				buf2Ptr += w2;
				d++;
				goto boucleVar2;
				}
			stuffBuffer(buf2Ptr, w1, localBuffer);
			stuffBuffer(buf2Ptr, w2, localBuffer);
			d++;
			goto boucleVar2;
			}
		}
	if (buf2Ptr >= 4)
		{
		memcpy(&w1, &localBuffer[buf2Ptr-2],2);
		memcpy(&w2, &localBuffer[buf2Ptr-4],2);
		if (w1 == 0 && w2 < 0)
			buf2Ptr -=2;
		}
	stuffBuffer(buf2Ptr,s,localBuffer);
	stuffBuffer(buf2Ptr,0,localBuffer);
	count = buf2Ptr;
	return localBuffer;

}


int isVariable(signed int w1, signed int w2)
{

return (w1 > 0);
#pragma warn -par
}
#pragma warn .par


void getPair(signed int& w1, signed int& w2)
{
_fread(&w1, 2, 1, _in);
_fread(&w2, 2, 1, _in);
}

char *varContents(int argNum)
{
double data;
unsigned long data_long;
unsigned int data_int;
unsigned char data_char;
unsigned int data_id;
unsigned int data_len,a;
float data_float;
char *str;
char *retour, *work;
char k[2]="X";

if (variable[argNum].predef != 0)
	return toVar(argNum);


data_id = variable[argNum].ID;
memcpy(&data,&variable[argNum].data,8);
memcpy(&data_long,&variable[argNum].data,4);
memcpy(&data_int,&variable[argNum].data,2);
memcpy(&data_char,&variable[argNum].data,1);
memcpy(&str, &variable[argNum].data[4],4);
memcpy(&data_len, &variable[argNum].data[2],2);

switch (variable[argNum].Type & 0xFF)
	{
	case 0:
		retour = (char *)calloc(6,1);
		if (data)
			strcpy(retour,"TRUE");
		else
			strcpy(retour,"FALSE");
		break;

	case 1:
		retour = (char *)calloc(16,1);
		ultoa(data_long,retour,10);
		break;

	case 2:
	case 3:
	case 0xA:
		retour = (char *)calloc(7,1);
		sprintf(retour,"%u",data_int);
		break;

	case 4:
	case 5:
	case 8:
		retour = (char *)calloc(16,1);
		ltoa(data_long,retour,10);
		break;

	case 6:
	case 0xE:
		retour = (char *)calloc(16,1);
		sprintf(retour,"%g",data);
		break;

	case 7:
	case 0xD:
		retour = (char *)calloc(data_len+3,1);
        work = (char *)calloc(data_len+255,1);

        if (data_len > 0)
            for (a=0;a<strlen(str);a++)
        	    {
                k[0] = str[a];
                mystrcat(work, k);
                if (str[a] == '\"')
	                mystrcat(work, k);
                }

		strcpy(retour,"\"");
        if (data_len > 0)
			strcat(retour,work);
		strcat(retour,"\"");

        free(work);
		break;

	case 9:
		retour = (char *)calloc(5,1);
		sprintf(retour,"%c",data_char);
		break;

	case 0xB:
		retour = (char *)calloc(5,1);
		if ((signed) data_char < 0)
			sprintf(retour,"-%c",~data_char);
		else
			sprintf(retour,"%c",data_char);
		break;

	case 0xC:
		retour = (char *)calloc(7,1);
		sprintf(retour,"%d",data_int);
		break;

	case 0xF:
		retour = (char*)calloc(13,1);
		sprintf(retour,"FUNCTION%03d",variable[data_id].index);
		break;

	case 0x10:
		retour = (char*)calloc(14,1);
		sprintf(retour,"PROC%03d",variable[data_id].index);
		break;
	default :
		retour = (char *)calloc(2,1);
		*retour = 0;
	}
return retour;
}

int gotoInTable(int a)
{
int b;
for (b=0;b<gotoIndex;b++)
	if (a == gotoTable[b])
		return 1;
return 0;
}

int getGotoIndex(int a)
{
int b;
for (b=0;b<gotoIndex;b++)
	if (a == gotoTable[b])
		return b;
return 0;
}

int procInTable(int a)
{
int b;
for (b=0;b<procIndex;b++)
	if (a == procTable[b])
		return 1;
return 0;
}

int getProcIndex(int a)
{
int b,c;
for (b=0;b<procIndex;b++)
	if (a == procTable[b])
		{
		for (b=0;b<totalVar;b++)
			if ((variable[b].Type == 0x10) || (variable[b].Type == 0x0F))
				{
				memcpy(&c, &variable[b].data[2],2);
				if (c == a)
					return b;
				}
		}
return 0;
}

void checkFunction(int function)
{
if (!strcmp(Function[~function+1].name,"") || (~function+1 > HiFunction) || ~function+1 == 0)
    errorMessage("Failed!\nFATAL ERROR 6: Unknown function!");

if (!noanalysis)
	if (pass == 2)
		{
		if (~function+1 == 73) // pcbdat
			flag[14]=1;
		if (~function+1 == 112 || ~function+1 == 113 || ~function+1 == 157) // peek/peekw/peekdw
			flag[15]=1;
		if (~function+1 == 132) // u_pwdhist
			flag[16]=1;
		if (~function+1 == 0x10C || ~function+1 == 0x10D) // findfirst/findnext
			flag[17]=1;
		if (~function+1 == 0x51) // sysopsec
			flag[18]=1;
		}
}



void mystrcat(char *&dest, char *src)
{
char *temp;

int a = ((strlen(dest) + strlen(src)) >> 6)+1;
temp = (char *)calloc(a*64,1);
strcpy(temp,dest);
dest=my_free(dest);
dest = temp;
strcat(dest,src);

}

void mystrncat(char *&dest, char *src, int count)
{
char *temp;

int a = ((strlen(dest) + count) >> 6)+1;
temp = (char *)calloc(a*64,1);
strcpy(temp,dest);
dest=my_free(dest);
dest = temp;

strncat(dest,src,count);

}

void mystrcpy(char *&dest, char *src)
{

int a = ((strlen(dest) + strlen(src)) >> 6)+1;
dest=my_free(dest);
dest = (char *)calloc(a*64,1);

strcpy(dest,src);

}

void mystrncpy(char *&dest, char *src, int count)
{

int a = (count >> 6)+1;
dest=my_free(dest);
dest = (char *)calloc(a*64,1);

strncpy(dest,src,count);

}

char *my_free(void *ptr)
{
if (!ptr)
    errorMessage(memError);

free(ptr);
return NULL;
}

char *toVar(int a)
{
char *t;

if (variable[a].predef == 15)
	flag[16] = 1;

t = (char *)calloc(256,1);
if (variable[a].nDim > 0)
	if (variable[a].predef != 0)
		sprintf(t,"%s(",Predef[variable[a].predef]);
	else
		sprintf(t,"T%s%03d(",UType[variable[a].Type],variable[a].index);
else
	if (variable[a].predef != 0)
		sprintf(t,"%s",Predef[variable[a].predef]);
	else
		sprintf(t,"%s%03d",UType[variable[a].Type],variable[a].index);

return t;
}

int sort_function( const void *a, const void *b)
{
   if (*(int *)a < *(int *)b) return -1;
   if (*(int *)a > *(int *)b) return 1;
   return 0;
}


void errorMessage(char *str)
{
printf(str);
fcloseall();
if (format == 3)
	unlink(filenameSource);

cout << "\n\nPlease, be sure you use the latest version of PPLX, if so, this\n";
cout << "PPE surely has some tricks that PPLX does not handle... Please, please...\n";
cout << "send this PPE uuencoded to lone.runner@nuxes.frmug.fr.net so i can fix this.\n";
exit(1);
}

void cursorOff(void)
{
union REGS regs;

regs.x.ax = 0x0100;
regs.x.cx = 0x2000;
int86(0x10, &regs, &regs);
}

void cursorOn(void)
{
union REGS regs;

regs.x.ax = 0x0100;
regs.x.cx = 0x0607;
int86(0x10, &regs, &regs);
}
