/////////////////////////////////////////////
//* Custom Firmware Extender 2.1 Firmware *//
/////////////////////////////////////////////

#include <psptypes.h>
#include <pspkernel.h>
#include <string.h>
#include <stdio.h>
#include <pspusb.h>
#include <psppower.h>
#include <pspdisplay.h>
#include <pspdisplay_kernel.h>
#include <pspusbstor.h>

#include "../include/systemctrl_se.h"
#include "../include/pspmodulemgr_kernel.h"
#include "../include/systemctrl.h"
#include "../include/pspsysmem_kernel.h"

#include "main.h"
#include "screenshot.h"
#include "conf.h"
#include "translateButtons.h"

#include "blit.h"

PSP_MODULE_INFO("cfe_vsh_mod", 0x1000, 1, 1);
PSP_MAIN_THREAD_ATTR(0);
PSP_MAIN_THREAD_STACK_SIZE_KB(0);

#define HOSTFSDRIVER_NAME "USBHostFSDriver"
#define HOSTFSDRIVER_PID  (0x1C9)

#define PSP_USBBUS_DRIVERNAME "USBBusDriver"
#define PSP_USBSTOR_DRIVERNAME "USBStor_Driver"
#define PSP_USB_ACTIVATED              0x200

char strBuf0[64];
char strBuf1[64];
char strBuf2[64];
char strBuf3[64];
char strBuf4[64];
char strBuf5[64];
char strBuf6[64];
char strBuf7[64];
char strBuf8[64];
char strBuf9[64];

char strMsg[128];

int showMsg = 0;
int showUsbhostMenu = 0;
int showHelp = 0;

int cpuSpeed = 222;
int webBrowserLoaded = 0;
int usbMass = 0;
int usbModules = 0;
int firstBoot = 0;
int stopSleepMode = 0;
int usbhostLoaded = 0;
int menuDone = 0;
int kill_display = 0;

int usePspFat = 0;

int usbmodloaded = 0;
int remotejoy =0;

char fullpath[30][128];
char fullpath_ms0[30][128];
int num = 0;

u32 state;
u32 retVal;

int showMusicMenuEnabled=0;

SceCtrlData pad;
SceCtrlData padIso;
unsigned int pad_old;

SceUID main_thid;
SceUID display_thid;

CONFIGFILE config;

int cleanExit;

int showStreamMenu = 0;

int showFps = 0;

int vshBlit(char *msg)
{
	strcpy(strMsg, msg);
	showMsg=1;
	return 0;
}	


int build_args(char *args, const char *execfile, int argc, char **argv)
{
	int loc = 0;
	int i;

	strcpy(args, execfile);
	loc += strlen(execfile) + 1;
	for(i = 0; i < argc; i++)
	{
		strcpy(&args[loc], argv[i]);
		printf("Arg %i => %s\n", i, argv[i]);
		loc += strlen(argv[i]) + 1;
	}

	return loc;
}

int loadStartModule(const char *name, int argc, char **argv)
{
	SceUID modid;
	int status;
	char args[128];
	int len;

	//modid = kuKernelLoadModule(name, 0, NULL);
	modid = sceKernelLoadModule(name, 0, NULL);
	if(modid >= 0)
	{
		len = build_args(args, name, argc, argv);
		modid = sceKernelStartModule(modid, len, (void *) args, &status, NULL);
		char tmp[32];
		strcpy(tmp, "module loaded : ");
		strcat(tmp, name);
		vshBlit(tmp);
	}
	else
	{
		char tmp[32];
		strcpy(tmp, "lsm: Error loading module ");
		strcat(tmp, name);
		vshBlit(tmp);
		printf("lsm: Error loading module %s\n", name);
	}

	return modid;
}

int unloadStopModule(char *modname)
{
	SceModule *mod;

	while ((mod = sceKernelFindModuleByName(modname)))
	{
		sceKernelStopModule(mod->modid, 0, NULL, NULL, NULL);
		sceKernelUnloadModule(mod->modid);
	}

	return 0;

}

void usbhostStart()
{
	int retVal = 0;

	retVal = sceUsbStart(PSP_USBBUS_DRIVERNAME, 0, 0);
	if (retVal != 0) {
		Kprintf("Error starting USB Bus driver (0x%08X)\n", retVal);
		return 0;
	}
	retVal = sceUsbStart(HOSTFSDRIVER_NAME, 0, 0);
	if (retVal != 0) {
		Kprintf("Error starting USB Host driver (0x%08X)\n",
		   retVal);
		return 0;
	}

	retVal = sceUsbActivate(HOSTFSDRIVER_PID);
}

int remotejoyStart()
{
	int ARGC;
	char * argv[ARGC];
	int argc = ARGC;
	
	char param0[]="1";

	argv[0] = param0;
	
	argv[argc] = NULL;
	
	loadStartModule("ms0:/seplugins/cfe/remotejoy.prx", 1, &argv);
	
	return 0;
}

int display_thread(SceSize args, void *argp)
{
    while(1) 
	{
		/*if(showFps) {
			//sprintf(strBuf0,"%03d fps",sceDisplay_driver_13AA96B7()/1000.0f);
			sprintf(strBuf0,"fps: %d.%03d",sceDisplay_driver_13AA96B7(),sceDisplay_driver_13AA96B7()* 1000.0f);
			blit_string(1, 1, strBuf0,0xffffff,0x000000);
		}*/
		
		if(kill_display) 
		{
			sceKernelExitDeleteThread(0);
		}
		
		if(showMsg)
		{
			blit_string(1,33,strMsg,0xffffff,0x000000);
			showMsg++;
			if(showMsg==600) showMsg=0;			
		}

		if(showHelp)
		{
			blit_string(1, 9, "Custom Firmware Extender 2.2",0xffffff,0x000000);
			blit_string(1, 10, "================================",0xffffff,0x000000);
			blit_string(1, 12, strBuf0,0xffffff,0x000000);
			blit_string(1, 14, strBuf1,0xffffff,0x000000);
			blit_string(1, 16, strBuf2,0xffffff,0x000000);
			blit_string(1, 18, strBuf3,0xffffff,0x000000);
			blit_string(1, 20, strBuf4,0xffffff,0x000000);
			blit_string(1, 22, strBuf5,0xffffff,0x000000);
			blit_string(1, 24, strBuf6,0xffffff,0x000000);
			blit_string(1, 26, strBuf7,0xffffff,0x000000);
			blit_string(1, 28, strBuf8,0xffffff,0x000000);
			blit_string(1, 30, strBuf9,0xffffff,0x000000);
			blit_string(1, 32, "Circle = Hide This Help",0xffffff,0x000000);
		}

		if(showMusicMenuEnabled)
		{
			blit_string(1, 9, "Custom Firmware Extender Music Menu",0xffffff,0x000000);
			blit_string(1, 10, "======================================",0xffffff,0x000000);
			blit_string(1, 12, "START => Play/Pause Song",0xffffff,0x000000);
			blit_string(1, 14, "UP => Volume Up",0xffffff,0x000000);
			blit_string(1, 16, "DOWN => Volume Down",0xffffff,0x000000);
			blit_string(1, 18, "L => Previous Song",0xffffff,0x000000);
			blit_string(1, 20, "R => Next Song",0xffffff,0x000000);
			blit_string(1, 22, "SELECT => In-game Mute/Unmute",0xffffff,0x000000);
			blit_string(1, 24, "LEFT => Random Playback",0xffffff,0x000000);
			blit_string(1, 26, "RIGHT => Loop Playback",0xffffff,0x000000);
			blit_string(1, 28, "CIRCLE = Exit Menu",0xffffff,0x000000);
		}
		sceKernelDelayThread(2000);
	}
	return 0;
}

void unloadUsb() {

	sceUsbDeactivate(0x1c8);
	sceUsbStop(PSP_USBSTOR_DRIVERNAME, 0, 0); //sceUsbStop
  	sceUsbStop(PSP_USBBUS_DRIVERNAME, 0, 0);
	usbModules=0;
}

int loadUsb(void) {

	if(!usbModules) 
	{
		if(!usbmodloaded) {
			loadStartModule("flash0:/kd/semawm.prx", 0, NULL);
			loadStartModule("flash0:/kd/usbstor.prx", 0, NULL);
			loadStartModule("flash0:/kd/usbstormgr.prx", 0, NULL);
			loadStartModule("flash0:/kd/usbstorms.prx", 0, NULL);
			loadStartModule("flash0:/kd/usbstorboot.prx", 0, NULL);
			usbmodloaded=1;
		}
		
		retVal = sceUsbStart(PSP_USBBUS_DRIVERNAME, 0, 0); //sceUsbStart
		if (retVal != 0) {
			printf("Error starting USB Bus driver\n");
			sceKernelSleepThread();
		}
		retVal = sceUsbStart(PSP_USBSTOR_DRIVERNAME, 0, 0); //sceUsbStart
		if (retVal != 0) {
			printf("Error starting USB Mass Storage driver\n");
			sceKernelSleepThread();
		}
		retVal = sceUsbstorBootSetCapacity(0x800000); //sceUsbstorBootSetCapacity
		if (retVal != 0) {
			printf("Error setting capacity with USB Mass Storage driver\n");
			sceKernelSleepThread();
		}
		retVal = 0;
		sceKernelDelayThread(5*10000);
		usbModules=1;
	}

	if (state & PSP_USB_ACTIVATED) {
		//retVal = sceUsb_driver_C572A9C8(0x1c8);
		unloadUsb();
		if(!firstBoot) 	vshBlit("Usb Mass Storage Stopped");
	}
	else {
		retVal = sceUsbActivate(0x1c8); //sceUsbActivate
		if(!firstBoot) vshBlit("Usb Mass Storage Started");
	}
	return 0;
}

void unloadUsbhost() {

	sceUsbDeactivate(HOSTFSDRIVER_PID);
	sceUsbStop(HOSTFSDRIVER_NAME, 0, 0); //sceUsbStop
  	sceUsbStop(PSP_USBBUS_DRIVERNAME, 0, 0);
	unloadStopModule("USBHostFS");
}

void setCpuSpeed(void)
{
	switch(cpuSpeed) {

		case 111:
			scePowerSetClockFrequency(111, 111, 55);
			cpuSpeed=222;
			sceKernelDelayThread(10000);
			if(!firstBoot) {
				sprintf(strBuf0,"Cpu/Bus Speed => %03d/%03d",scePowerGetCpuClockFrequency(),scePowerGetBusClockFrequency());
				vshBlit(strBuf0);
			}			
			break;		
	
		case 222:
			scePowerSetClockFrequency(222, 222, 111);
			cpuSpeed=266;
			sceKernelDelayThread(10000);
			if(!firstBoot) {
				sprintf(strBuf0,"Cpu/Bus Speed => %03d/%03d",scePowerGetCpuClockFrequency(),scePowerGetBusClockFrequency());
				vshBlit(strBuf0);
			}			
			break;
					
		case 266:
			scePowerSetClockFrequency(266, 266, 133);
			cpuSpeed=333;
			sceKernelDelayThread(10000);
			if(!firstBoot) {
				sprintf(strBuf0,"Cpu/Bus Speed => %03d/%03d",scePowerGetCpuClockFrequency(),scePowerGetBusClockFrequency());
				vshBlit(strBuf0);
			}
			break;
	
		case 333:
			scePowerSetClockFrequency(333, 333, 166);
			cpuSpeed=66;
			sceKernelDelayThread(10000);
			if(!firstBoot) {
				sprintf(strBuf0,"Cpu/Bus Speed => %03d/%03d",scePowerGetCpuClockFrequency(),scePowerGetBusClockFrequency());
				vshBlit(strBuf0);
			}
			break;
	
		case 66:
			scePowerSetClockFrequency(66, 66, 33);
			cpuSpeed=111;
			sceKernelDelayThread(10000);
			if(!firstBoot) {
				sprintf(strBuf0,"Cpu/Bus Speed => %03d/%03d",scePowerGetCpuClockFrequency(),scePowerGetBusClockFrequency());
				vshBlit(strBuf0);
			}
			break;
	}
}

int hookWait = 0;
int hookWait2 = 0;

void execEboot(char *target)
{
	cleanExit = 0;
			
	sceKernelDelayThread(1000);
			
	kill_display=1;
			
	sceKernelDelayThread(1000);

	struct SceKernelLoadExecVSHParam param;
			
	memset(&param, 0, sizeof(param));
			
	param.key = "game";
	param.size = sizeof(param);
	param.args = strlen(target)+1;
	param.argp = target;
	
	nkThreadResume(sceKernelGetThreadId());
	
	sctrlKernelLoadExecVSHMs2(target, &param);	
	
	sceKernelExitDeleteThread(0);
}


int vshHook()
{
	
	if(hookWait>0) hookWait--;
	
	if(!hookWait) 
	{	
		if(enable_replace_video_icon_with)
		{		
			if(sceKernelFindModuleByName("msvideo_plugin_module"))  // video
			{
				nkThreadSuspend(sceKernelGetThreadId());
				execEboot(config.replace_video_icon_with);
			}
		}

		if(enable_replace_locationFree_icon_with)
		{			
			if(sceKernelFindModuleByName("lftv_plugin_module")) // Location Free
			{
				nkThreadSuspend(sceKernelGetThreadId());
				execEboot(config.replace_locationFree_icon_with);
			}
		}

		if(enable_replace_remotePlay_icon_with)
		{			
			if(sceKernelFindModuleByName("premo_plugin_module")) // Lecture à distance
			{
				nkThreadSuspend(sceKernelGetThreadId());
				execEboot(config.replace_remotePlay_icon_with);
			}
		}

		if(enable_replace_rss_icon_with)
		{	
			if(sceKernelFindModuleByName("rss_main_plugin_module")) // Rss
			{
				nkThreadSuspend(sceKernelGetThreadId());
				execEboot(config.replace_rss_icon_with);
			}
		}
		
		if(enable_replace_gameSharing_icon_with)
		{			
			if(sceKernelFindModuleByName("sceVshGSPlugin_Module")) // Partage de jeu
			{
				nkThreadSuspend(sceKernelGetThreadId());
				execEboot(config.replace_gameSharing_icon_with);
			}
		}
		
		if(enable_replace_update_icon_with)
		{
			if(sceKernelFindModuleByName("update_plugin_module")) // Update
			{
				nkThreadSuspend(sceKernelGetThreadId());
				execEboot(config.replace_update_icon_with);
			}
		}

		if(enable_replace_camera_icon_with)
		{
			if(sceKernelFindModuleByName("camera_plugin_module")) // Camera
			{
				nkThreadSuspend(sceKernelGetThreadId());
				execEboot(config.replace_camera_icon_with);
			}
		}		
		hookWait = 100;
	}
	return 0;	
}

void cleanBeforeExit() {

	if(hookWait2>0) hookWait2--;
	
	if(!hookWait2)
	{
		SceUID thids[50];
		int thid_count = 0;
		int i;
		SceKernelThreadInfo thinfo;

		sceKernelGetThreadmanIdList(SCE_KERNEL_TMID_Thread,thids,50,&thid_count);
		for(i=0;i<thid_count;i++)
			{
			memset(&thinfo,0,sizeof(SceKernelThreadInfo));
			thinfo.size = sizeof(SceKernelThreadInfo);
            
			sceKernelReferThreadStatus(thids[i],&thinfo);

			if(strcmp(&thinfo.name[0],"SceKernelLoadExecThread")==0)
			{
				menuDone = 1;
				scePowerSetClockFrequency(222, 222, 111);
				if(usbModules) unloadUsb();
				sceKernelTerminateDeleteThread(main_thid);
				sceKernelSelfStopUnloadModule(1, 0, NULL); 
			}
		}
		hookWait2 = 100;
		
	}
}

int helpMenu() 
{	
	menuDone=0;
	
	sprintf(strBuf0, "%s + %s = Shutdown PSP", config.comboButton, config.poweroffButton);
	sprintf(strBuf1, "%s + %s = Reboot to %s", config.comboButton, config.resetButton1, config.resetButton1_TM_BOOT);
	sprintf(strBuf2, "%s + %s = Reboot to %s", config.comboButton, config.resetButton2, config.resetButton2_TM_BOOT);
	sprintf(strBuf3, "%s + %s = Change Cpu Speed", config.comboButton, config.cpuspeedButton);
	sprintf(strBuf4, "%s + %s = Set Max Brightness", config.comboButton, config.maxBrightnessButton);
	sprintf(strBuf5, "%s + %s = Start/Stop Usb Mass", config.comboButton, config.startStopUsbmassButton);
	sprintf(strBuf6, "%s + %s = Start Ftpd server", config.comboButton, config.startFtpdButton);
	sprintf(strBuf7, "%s + %s = Take Screenshot", config.comboButton, config.takeScreenshotButton);
	sprintf(strBuf8, "%s + %s = Start RemoteJoy (video capture)", config.comboButton, config.captureButton);
	sprintf(strBuf9, "%s + %s = Show this help", config.comboButton, config.showHelpButton);	
	
	nkThreadSuspend(sceKernelGetThreadId());
	
	while(!menuDone)
	{
		cleanBeforeExit();
		
		showHelp=1;
		
		sceDisplayWaitVblankStart();
		
		sceCtrlPeekBufferPositive(&pad, 1);
		if (pad.Buttons != pad_old)
		{	
			if(pad.Buttons & PSP_CTRL_CIRCLE) 
			{
				nkThreadResume(sceKernelGetThreadId());
				showHelp=0;
				menuDone=1;
			}
		}
	}
	pad_old = pad.Buttons;
	sceKernelDelayThread(1000);
	
	return 0;
}

void setBrightness(int x)
{
	sceDisplaySetBrightness(x,0);
}

void checkUnloadBrowser() {

	SceUID thids[50];
	int thid_count = 0;
	int i;
	SceKernelThreadInfo thinfo;

	sceKernelGetThreadmanIdList(SCE_KERNEL_TMID_Thread,thids,50,&thid_count);
	for(i=0;i<thid_count;i++)
        {
		memset(&thinfo,0,sizeof(SceKernelThreadInfo));
		thinfo.size = sizeof(SceKernelThreadInfo);

		sceKernelReferThreadStatus(thids[i],&thinfo);

		if(strcmp(&thinfo.name[0],"SceHtmlViewer")==0)
		{
			webBrowserLoaded=1;

			//sceKernelTerminateDeleteThread(thids[i]);
		}
	}
}

int musicModuleLoaded=0;

const char* vshMusicDir()
{
        const char* p;
        sceKernelDelayThread(10000);
 
        p = config.music_dir;
        return p; 
}

const char* vshMusicButton()
{
        const char* q;
        sceKernelDelayThread(10000);
 
        q = config.comboButton;
        return q; 
}

const char* vshComboButton()
{
        const char* r;
        sceKernelDelayThread(10000);
 
        r = config.musicButton;
        return r; 
}

char write_buffer[128*1024];

void copy_file(const char *read_loc, const char *write_loc)
{
	int fdin;
	int fdout;

	fdin = sceIoOpen(read_loc, PSP_O_RDONLY, 0511);
	if(fdin >= 0)
	{
		int bytesRead = 1;
		fdout = sceIoOpen(write_loc, PSP_O_WRONLY | PSP_O_CREAT | PSP_O_TRUNC, 0777);
		if(fdout < 0)
		{
			printf("Couldn't open %s\n", write_loc);
		}

		bytesRead = sceIoRead(fdin, write_buffer, sizeof(write_buffer));
		while((bytesRead > 0) && (fdout >= 0))
		{
			sceIoWrite(fdout, write_buffer, bytesRead);
			bytesRead = sceIoRead(fdin, write_buffer, sizeof(write_buffer));
		}

		if(fdout >= 0)
		{
			sceIoClose(fdout);
		}

		if(fdin >= 0)
		{
			sceIoClose(fdin);
		}
	}
	else
	{
		printf("Couldn't open %s\n", read_loc);
	}
}

void restore_tm_config()
{
	int fd = sceIoOpen("ms0:/TM/config.txt.back", PSP_O_RDONLY, 0511);
	if(fd < 0) 
	{
		sceIoClose(fd);
	}
	else
	{
		sceIoClose(fd);
		sceIoRemove("ms0:/TM/config.txt");
		copy_file("ms0:/TM/config.txt.back", "ms0:/TM/config.txt");
		sceIoRemove("ms0:/TM/config.txt.back");
	}
}

int threadMain(SceSize args, void *argp)
{
	firstBoot = 1;
	state = 0;
	cleanExit = 1;
	
	read_config("ms0:/seplugins/cfe/cfe.config", &config);
	sceKernelDelayThread(10000);
	
	while(!translateButtons()) {
		printf("waiting\n");
	}
	
	sceKernelDelayThread(20*100000);
	
	state = sceUsbGetState();
	if(config.enableUsbMass) loadUsb();
	
	cpuSpeed=config.defaultCpuSpeedVsh;
	setCpuSpeed();
	
	if(defaultBrightnessEnable) setBrightness(config.defaultBrightnessVsh);
	
	firstBoot=0;

	if(config.use_TM_functions) restore_tm_config();

	while(1) {

		state = sceUsbGetState();

		//if(cleanExit) cleanBeforeExit();
		
		vshHook();
		
		if(stopSleepMode) scePowerTick(0);

		sceCtrlPeekBufferPositive(&pad, 1);
		
		if (pad.Buttons != pad_old)
		{		
			if(poweroffEnable) 
			{
				if((pad.Buttons & (poweroffButton_i | comboButton_i)) == (poweroffButton_i | comboButton_i))				
				{
					scePowerRequestStandby();
				}
			}

			if(reset1Enable) 
			{	
				if((pad.Buttons & (resetButton1_i | comboButton_i)) == (resetButton1_i | comboButton_i))
				{
					if(config.use_TM_functions)
					{
						copy_file("ms0:/TM/config.txt", "ms0:/TM/config.txt.back");
						sceIoRemove("ms0:/TM/config.txt");
		
						int fd = sceIoOpen("ms0:/TM/config.txt", PSP_O_CREAT | PSP_O_RDWR, 0777);
						if(fd < 0) 
						{
							sceIoClose(fd);
						}
						else
						{
							char temp[48];
							strcpy(temp, "NOTHING = \"");
							strcat(temp, config.resetButton1_TM_BOOT);
							strcat(temp, "\";");
							sceIoWrite(fd, temp, 48);
							sceIoClose(fd);
						}
					}
					sceKernelDelayThread(10000);
					scePower_driver_0442D852();
				}	
			}
			if(reset2Enable) 
			{	
				if((pad.Buttons & (resetButton2_i | comboButton_i)) == (resetButton2_i | comboButton_i))
				{
					if(config.use_TM_functions)
					{
						copy_file("ms0:/TM/config.txt", "ms0:/TM/config.txt.back");
						sceIoRemove("ms0:/TM/config.txt");
		
						int fd = sceIoOpen("ms0:/TM/config.txt", PSP_O_CREAT | PSP_O_RDWR, 0777);
						if(fd < 0) 
						{
							sceIoClose(fd);
						}
						else
						{
							char temp[48];
							strcpy(temp, "NOTHING = \"");
							strcat(temp, config.resetButton2_TM_BOOT);
							strcat(temp, "\";");
							sceIoWrite(fd, temp, 48);
							sceIoClose(fd);
						}
					}
					sceKernelDelayThread(10000);
					scePower_driver_0442D852();
				}	
			}
			
			if(cpuspeedEnable) {
				if((pad.Buttons & (cpuspeedButton_i | comboButton_i)) == (cpuspeedButton_i | comboButton_i))			
				{
					setCpuSpeed();
				}
			}

			if(maxBrightnessEnable) {	
				if((pad.Buttons & (maxBrightnessButton_i | comboButton_i)) == (maxBrightnessButton_i | comboButton_i))
				{
					setBrightness(99);
					vshBlit("Brightness set to maximum value");
				}
			}
			
			if(takeScreenshotEnable) 
			{
				if((pad.Buttons & (takeScreenshotButton_i | comboButton_i)) == (takeScreenshotButton_i | comboButton_i))			
				{
					int plop = sceIoDopen(config.captureFolder);
	
					if (plop >= 0)
					{
						printf("Directory already exist\n");					
					} 
					else {
						sceIoMkdir(config.captureFolder, 0777);
					}
						
					screenshot();
					sprintf(strBuf0,"Screenshot saved to %s", file);
					vshBlit(strBuf0);
				}	
			}
			
			if(showHelpEnable)
			{
				if((pad.Buttons & (showHelpButton_i | comboButton_i)) == (showHelpButton_i | comboButton_i))
				{
					helpMenu();
				}
			}
			
			if(startStopUsbmassEnable) {
				if((pad.Buttons & (startStopUsbmassButton_i | comboButton_i)) == (startStopUsbmassButton_i | comboButton_i))
				{
					loadUsb();				
				}
			}
			
			if(startFtpdEnable) {
				if((pad.Buttons & (startFtpdButton_i | comboButton_i)) == (startFtpdButton_i | comboButton_i))
				{
					checkUnloadBrowser();
					sceKernelDelayThread(5*10000);
					if(!webBrowserLoaded) {
						scePowerSetClockFrequency(333, 333, 166);
						loadStartModule("ms0:/seplugins/cfe/cfe_ftpd.prx", 0, NULL);
						stopSleepMode=1;
					}
				}
				if(pad.Buttons & PSP_CTRL_CIRCLE) stopSleepMode=0;
			}

			if(captureEnable) 
			{
				if((pad.Buttons & (captureButton_i | comboButton_i)) == (captureButton_i | comboButton_i))
				{
					if(!remotejoy) 
					{
						vshBlit("Starting remotejoy video capture plugin");
						sceKernelDelayThread(10*100000);
						loadStartModule("ms0:/seplugins/cfe/usbhostfs.prx", 0, NULL);	
						//usbhostStart();
						sceKernelDelayThread(20*100000);	
						//loadStartModule("ms0:/seplugins/cfe/remotejoy.prx", 0, NULL);
						remotejoyStart();
						sceKernelDelayThread(20*100000);
	
						remotejoy=1;	
						vshBlit("Done");
							
					} 
					else
					{
						vshBlit("Stoping remotejoy video capture plugin");	
						remotejoyShutdown(); // exported by remotejoy.prx
						unloadUsbhost();
						remotejoy=0;
					}
				}
			 }
	
			if(musicButtonEnable)
			{
				if((pad.Buttons & (musicButton_i | comboButton_i)) == (musicButton_i | comboButton_i))	
				{
					if(!musicModuleLoaded) loadStartModule("ms0:/seplugins/cfe/cfe_music.prx", 0, NULL);
					musicModuleLoaded=1;
					showMusicMenuEnabled=1;
					while(!menuDone)
					{
						sceCtrlPeekBufferPositive(&pad, 1);
						if (pad.Buttons != pad_old)
						{	
							if(pad.Buttons & PSP_CTRL_CIRCLE) 
							{
								
								showMusicMenuEnabled=0;
								//menuDone=1;
								break;
							}
						}
						pad_old = pad.Buttons;
						sceKernelDelayThread(1000);
					}
					menuDone=0;
				}
			}
			
		}
		pad_old = pad.Buttons;
		sceKernelDelayThread(1000);
	}
	return 0;
}

int module_start(SceSize args, void *argp)
{
	
	display_thid = sceKernelCreateThread("cfe_vsh_display", display_thread, 8, 0x400, 0, NULL);
	if(display_thid >= 0) sceKernelStartThread(display_thid, args, argp);
	
	nkLoad();
	
	main_thid = sceKernelCreateThread("cfe_vsh_main", threadMain, 6, 0x4000, 0, NULL);
	if(main_thid >= 0) sceKernelStartThread(main_thid, args, argp);

	return 0;

	sceKernelExitDeleteThread(0);
}

int module_stop(SceSize args, void *argp)
{
	return 0;
}
