/*

  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.

*/

/*
    PPE Decryption & Depacking routines, Thanks to Clark Development Company
*/

#include <dos.h>

int xor17=0;

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)
{
unsigned int wlen = len;
unsigned int parts = 1 + (unsigned int)len/2047;
unsigned int save;
unsigned int len2;
unsigned int ref=0;
unsigned int lastoff=0;
unsigned char lastbyte=1;
unsigned int dec=0;
unsigned int a;
char *startpointer;

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

save = 0;

/*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

	}
}
