
// UMD ripper par mph (mphtheone@hotmail.com)


// INCLUDES

#include "pg.h"			// Provient de HelloWorld de nem


// DEFINES

#define SIZEBLOC (16 * 1024)	// Taille du bloc de copie

// Provient du PSPSDK
#define PSP_O_RDONLY    0x0001
#define PSP_O_WRONLY    0x0002
#define PSP_O_RDWR      (PSP_O_RDONLY | PSP_O_WRONLY)
#define PSP_O_NBLOCK    0x0004
#define PSP_O_DIROPEN   0x0008  // Internal use for dopen
#define PSP_O_APPEND    0x0100
#define PSP_O_CREAT     0x0200
#define PSP_O_TRUNC     0x0400
#define PSP_O_EXCL      0x0800
#define PSP_O_NOWAIT    0x8000

#define PSP_SEEK_SET    0
#define PSP_SEEK_CUR    1
#define PSP_SEEK_END    2

// File mode checking macros
#define FIO_S_ISLNK(m)  (((m) & FIO_S_IFMT) == FIO_S_IFLNK)
#define FIO_S_ISREG(m)  (((m) & FIO_S_IFMT) == FIO_S_IFREG)
#define FIO_S_ISDIR(m)  (((m) & FIO_S_IFMT) == FIO_S_IFDIR)



// ENUMERATIONS

// Provient du PSPSDK
enum UmdDriveStat
{
 UMD_WAITFORDISC = 0x2,
 UMD_WAITFORINIT = 0x20
};

enum IOAccessModes
{
 FIO_S_IFMT              = 0xF000,
 FIO_S_IFLNK             = 0x4000,
 FIO_S_IFDIR             = 0x2000,
 FIO_S_IFREG             = 0x1000,

 FIO_S_ISUID             = 0x0800,
 FIO_S_ISGID             = 0x0400,
 FIO_S_ISVTX             = 0x0200,

 FIO_S_IRWXU             = 0x01C0,       
 FIO_S_IRUSR             = 0x0100,
 FIO_S_IWUSR             = 0x0080,
 FIO_S_IXUSR             = 0x0040,       
 
 FIO_S_IRWXG             = 0x0038,       
 FIO_S_IRGRP             = 0x0020,
 FIO_S_IWGRP             = 0x0010,
 FIO_S_IXGRP             = 0x0008,
 
 FIO_S_IRWXO             = 0x0007,       
 FIO_S_IROTH             = 0x0004,       
 FIO_S_IWOTH             = 0x0002,       
 FIO_S_IXOTH             = 0x0001,       
};


// STRUCTURES

// Provient du PSPSDK
typedef struct
{
 unsigned short year;
 unsigned short month;
 unsigned short day;
 unsigned short hour;
 unsigned short minute;
 unsigned short sec;
 unsigned short unk[2];
} io_time_t;

typedef struct
{
 unsigned int type;
 unsigned int mode;
 long long size;
 io_time_t ctime; 
 io_time_t atime; 
 io_time_t mtime; 
 unsigned int unk[6]; 
} io_stat_t;
 
typedef struct
{
 io_stat_t stat;
 char name[264];
 unsigned int dummy;
} io_dirent_t;


// VARIABLES GLOBALES

int fdg;			// Pour RAPPORT.TXT


// FONCTIONS GLOBALES

// Provient de RIN emulator (string.c)
int strlen(const char *s)
{
	int ret;
	
	for(ret=0; s[ret]; ret++)
		;
	
	return ret;
}

char* strcpy(char *dest, const char *src)
{
	int i;
	
	for(i=0; src[i]; i++)
		dest[i] = src[i];
	dest[i] = 0;
	
	return dest;
}

char* strcat(char *dest, const char *src)
{
	int i;
	int len;
	
	len=strlen(dest);
	for(i=0; src[i]; i++)
		dest[len+i] = src[i];
	dest[len+i] = 0;
	
	return dest;
}




int pow (int number, int exposant)
{
 int temp, x;

 temp = 1;
 for (x=0;x<exposant;x++) temp = temp * number;

 return temp;
}

void pgPrintNumber (int x, int y, int color, unsigned int number)
{
 int unite, temp, denom;


 // Pour le signe
 if (number < 0)
 {
  pgPutChar(x,y,color,0,'-',1,0,1);
  number = -number;
  x += 8;
 }

 if (number)
 {
  unite = 0;
  temp = number;

  while (temp)
  {
   temp /= 10;
   unite++;
  }
 }
 else
  unite = 1;

 for (temp=0,denom=pow(10,unite-1);temp<unite;temp++,denom/=10,x+=8) pgPutChar(x,y,color,0,'0' + ((number / denom) % 10),1,0,1);
}

int CopyFile (char *src, char *dest)
{
 int fd, fd2;
 unsigned int taille, x;
 char tab[SIZEBLOC];


 fd = sceIoOpen(src,PSP_O_RDONLY,0);
 if (!(fd)) return -1;

 fd2 = sceIoOpen(dest,PSP_O_WRONLY | PSP_O_CREAT | PSP_O_TRUNC,0777);
 if (!(fd2))
 {
  sceIoClose(fd);
  return -1;
 }

 taille = sceIoLseek32(fd,0,PSP_SEEK_END);
 sceIoLseek32(fd,0,PSP_SEEK_SET);

 while (taille)
 {
  x = (taille > SIZEBLOC) ? SIZEBLOC : taille;

  sceIoRead(fd,tab,x);
  sceIoWrite(fd2,tab,x);

  taille -= x;
 }

 sceIoClose(fd);
 sceIoClose(fd2);

 return 0;
}

int ScanFile_R (char *dir)
{
 io_dirent_t files[128];
 char src[512], dest[512];
 int x, fd, fd2;


 x = 0;
 fd = sceIoDopen(dir);
 if (fd < 0) return -1;

 while (sceIoDread(fd,&files[x]) > 0)
 {
  // Créer le nom source
  strcpy(src,dir);
  strcat(src,files[x].name);

  // Créer le nom de destination
  strcpy(dest,"ms0");
  strcat(dest,&dir[5]);
  strcat(dest,files[x].name);

  // Affiche les infos
  pgFillvram(0);
  pgPrint(2,5,0xFFFF,src);
  pgPrint(2,7,0xFFFF,"Vers");
  pgPrint(2,9,0xFFFF,dest);

  // Ecrit dans RAPPORT.TXT
  sceIoWrite(fdg,"\r\n",strlen("\r\n"));
  sceIoWrite(fdg,src,strlen(src));
  sceIoWrite(fdg,"\r\n",strlen("\r\n"));
  sceIoWrite(fdg,dest,strlen(dest));
  sceIoWrite(fdg,"\r\n",strlen("\r\n"));

  switch (files[x].stat.type & FIO_S_IFMT)
  {
  case FIO_S_IFREG :
    pgPrint(2,11,0xFFFF,"Type : Directory");
    pgScreenFlipV();

    sceIoWrite(fdg,"Type : Directory\r\n",strlen("Type : Directory\r\n"));

	// Crée le repertoire
	if (sceIoMkdir(dest,0777))
	{
	 sceIoDclose(fd);
	 return -1;	
	}

	strcat(src,"/");

	// Recursif pour chaque dossier
	if (ScanFile_R(src))
	{
	 sceIoDclose(fd);
	 return -1;	
	}

	src[strlen(src) - 2] = 0;
   break;

   case FIO_S_IFDIR :
    pgPrint(2,11,0xFFFF,"Type : File");
    pgScreenFlipV();

    sceIoWrite(fdg,"Type : File\r\n",strlen("Type : File\r\n"));

	if (CopyFile(src,dest))
	{
	 sceIoDclose(fd);
	 return -1;
	}
   break;
  }

  pgWaitVn(50);
  x++;
 }

 sceIoDclose(fd);

 return 0;
}

int exit_callback (void)
{
 sceKernelExitGame();

 return 0;
}

int CallbackThread (void *arg)
{
 int cbid;


 cbid = sceKernelCreateCallback("Exit Callback", exit_callback);
 sceKernelRegisterExitCallback(cbid);

 sceKernelSleepThreadCB();

 return 0;
}

int SetupCallbacks (void)
{
 int thid = 0;


 thid = sceKernelCreateThread("update_thread", CallbackThread, 0x11, 0xFA0, 0, 0);
 if (thid >= 0) sceKernelStartThread(thid, 0, 0);

 return thid;
}

int PSPMain (void)
{
 char tab[4096];
 unsigned int x, x2, taille;
 int fd, fd2;
 io_dirent_t dir;


 SetupCallbacks();

 // Initialiser l'ecran
 pgInit();
 pgScreenFrame(2,0);

 // Afficher le titre
 pgFillvram(0);
 pgPrint(20,10,0xFFFF,"Attente de l'umd");
 pgScreenFlipV();

 // Monter l'umd dans disc0
 x = sceUmdCheckMedium(0);
 if (!(x)) sceUmdWaitDriveStat(UMD_WAITFORDISC);

 sceUmdActivate(1,"disc0:");
 sceUmdWaitDriveStat(UMD_WAITFORINIT);

 // Ouvrir RAPPORT.TXT
 fdg = sceIoOpen("ms0:/RAPPORT.TXT",PSP_O_WRONLY | PSP_O_CREAT | PSP_O_TRUNC,0777);

 // Ripper l'umd
 ScanFile_R("disc0:/");

 // Fermer RAPPORT.TXT
 sceIoClose(fdg);

 // FIN
 pgFillvram(0);
 pgPrint(2,13,0xFFFF,"Copie de l'umd terminée, appuyer sur home pour quitter");
 pgScreenFlipV();

 while (1) pgWaitVn(100);

 return 0;
}
