/*
	Downgrade Control -> decrypt.c -> Responsible for decryption patches and hooks
	by Davee
	
	31/12/2010
*/

#include <pspkernel.h>
#include <pspsysmem_kernel.h>

#include <stdio.h>
#include <string.h>
#include <systemctrl.h>

#include "decrypt.h"
#include "patch_table.h"

int pspDecryptPRX(void *exec, u32 exec_size, u32 *out_size);

int (* sceMesgLed_driver_81F72B1F)(void *exec, u32 size, u32 *outsize) = NULL;

int sceResmgr_9DC14891_patched(void *data, u32 datasize, u32 *outsize)
{
	/* call the original function to decrypt the index.dat */
	int res = sceResmgr_driver_9DC14891(data, datasize, outsize);
	
	/* the default version */
	u32 fw_ver = 0x000;
	char temp_fw_ver[4];
	int ret;
	
	int k1 = pspSdkSetK1(0);
	ret = sceIdStorageLookup(0x51, 0, temp_fw_ver, 4);
	pspSdkSetK1(k1);
	
	/* now modify the firmware version to the factory installed OFW */
	if((ret < 0) && (sceKernelGetModel() == 0))
	{
		/* For 1000's, since they don't have the 0x51 key */
		fw_ver = 0x200;
	}
	else if(ret < 0)
	{
		/* Just incase some error happens, 635 is a safe bet */
		fw_ver = 0x635;
	}
	else
	{	
		/* Convert char array to value */
		fw_ver = ((temp_fw_ver[0] - '0') << 8) | ((temp_fw_ver[2] - '0') << 4) | (temp_fw_ver[3] - '0');
	}
	
	/* if there is a firmware version, we will generate a version.txt to downgrade */
	if (fw_ver)
	{
		sprintf( data,
				"release:%01X.%01X%01X:\n"
				"build:0000,0,3,1,0:builder@vsh-build6\n"
				"system:56422@release_%03X,0x%08X:\n"
				"vsh:p6576@release_%03X,v57929@release_%03X,20100625:\n"
				"target:1:WorldWide\n",
				/* first line, version (X.YZ) */ (fw_ver >> 8) & 0xF, (fw_ver >> 4) & 0xF, fw_ver & 0xF,
				/* third line, release_XYZ + devkit */ fw_ver, (((fw_ver >> 8) & 0xF) << 24) | (((fw_ver >> 4) & 0xF) << 16) | ((fw_ver & 0xF) << 8) | 0x10,
				/* forth line, release_XYZ + release_XYZ */ fw_ver, fw_ver
				);
	}
	
	/* return the decryption result */
	return res;
}

void PatchMesgled(u32 text_addr)
{
	/* if firmware is >= 6.30 */
	if (sceKernelDevkitVersion() >= 0x06030010)
	{
		int model = sceKernelGetModel();
		if(model == 6 || model == 8)
		{
			model = 3;
		}
		
		/* Patch mesgled to allow older updaters to boot */
		_sw(0, text_addr + g_patch_table.new_updater_check[model]);
	}
}

int sceMesgLed_driver_81F72B1F_patched(void *exec, u32 exec_size, u32 *out_size)
{
	/* do sony decryption */
	int res = sceMesgLed_driver_81F72B1F(exec, exec_size, out_size);
	
	/* check for error */
	if (res != 0)
	{
		/* lets decrypt */
		res = pspDecryptPRX(exec, exec_size, out_size);
	}
	
	/* return result */
	return res;
}

int memlmd_7CF1CD3E_patched(void *exec, u32 exec_size, u32 *out_size)
{
	/* do sony decryption */
	int res = memlmd_7CF1CD3E(exec, exec_size, out_size);
	
	/* check for error */
	if (res != 0)
	{
		/* lets decrypt */
		res = pspDecryptPRX(exec, exec_size, out_size);
	}
	
	/* return result */
	return res;
}
