mirror of
https://github.com/Fledge68/WiiFlow_Lite.git
synced 2024-11-27 13:44:15 +01:00
-DML view now can see games on usb too
-added possibility to copy gamecube games from usb to sd card, after copy process game will be started (copy takes 5-10 minutes) (issue 12) -added possibility to install gamecube games to usb fat partitions -fixed game name not displayed in delete game dialog -changed naming scheme of partition name in top-right corner in coverflow, now looks like DML [USB1], name depends on view
This commit is contained in:
parent
fa7da0a437
commit
f1d0386b3c
268
source/gc/fileOps.c
Normal file
268
source/gc/fileOps.c
Normal file
@ -0,0 +1,268 @@
|
|||||||
|
/*////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
fsop contains coomprensive set of function for file and folder handling
|
||||||
|
|
||||||
|
en exposed s_fsop fsop structure can be used by callback to update operation status
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <math.h>
|
||||||
|
#include <ogcsys.h>
|
||||||
|
#include <ogc/lwp_watchdog.h>
|
||||||
|
|
||||||
|
#include <dirent.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/stat.h> //for mkdir
|
||||||
|
#include <sys/statvfs.h>
|
||||||
|
|
||||||
|
#include "fileOps.h"
|
||||||
|
#include "memory/mem2.hpp"
|
||||||
|
#include "utils.h"
|
||||||
|
|
||||||
|
s_fsop fsop;
|
||||||
|
|
||||||
|
// return false if the file doesn't exist
|
||||||
|
bool fsop_GetFileSizeBytes (char *path, size_t *filesize) // for me stats st_size report always 0 :(
|
||||||
|
{
|
||||||
|
FILE *f;
|
||||||
|
size_t size = 0;
|
||||||
|
|
||||||
|
f = fopen(path, "rb");
|
||||||
|
if (!f)
|
||||||
|
{
|
||||||
|
if (filesize) *filesize = size;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Get file size
|
||||||
|
fseek( f, 0, SEEK_END);
|
||||||
|
size = ftell(f);
|
||||||
|
if (filesize) *filesize = size;
|
||||||
|
SAFE_CLOSE(f);
|
||||||
|
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Recursive fsop_GetFolderBytes
|
||||||
|
*/
|
||||||
|
u64 fsop_GetFolderBytes (char *source)
|
||||||
|
{
|
||||||
|
DIR *pdir;
|
||||||
|
struct dirent *pent;
|
||||||
|
char newSource[300];
|
||||||
|
u64 bytes = 0;
|
||||||
|
|
||||||
|
pdir=opendir(source);
|
||||||
|
|
||||||
|
while ((pent=readdir(pdir)) != NULL)
|
||||||
|
{
|
||||||
|
// Skip it
|
||||||
|
if (strcmp (pent->d_name, ".") == 0 || strcmp (pent->d_name, "..") == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
sprintf (newSource, "%s/%s", source, pent->d_name);
|
||||||
|
|
||||||
|
// If it is a folder... recurse...
|
||||||
|
if (fsop_DirExist (newSource))
|
||||||
|
{
|
||||||
|
bytes += fsop_GetFolderBytes (newSource);
|
||||||
|
}
|
||||||
|
else // It is a file !
|
||||||
|
{
|
||||||
|
size_t s;
|
||||||
|
fsop_GetFileSizeBytes (newSource, &s);
|
||||||
|
bytes += s;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
closedir(pdir);
|
||||||
|
|
||||||
|
//Debug ("fsop_GetFolderBytes (%s) = %llu", source, bytes);
|
||||||
|
|
||||||
|
return bytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 fsop_GetFolderKb (char *source)
|
||||||
|
{
|
||||||
|
u32 ret = (u32) round ((double)fsop_GetFolderBytes (source) / 1000.0);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 fsop_GetFreeSpaceKb (char *path) // Return free kb on the device passed
|
||||||
|
{
|
||||||
|
struct statvfs s;
|
||||||
|
|
||||||
|
statvfs (path, &s);
|
||||||
|
|
||||||
|
u32 ret = (u32)round( ((double)s.f_bfree / 1000.0) * s.f_bsize);
|
||||||
|
|
||||||
|
return ret ;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool fsop_DirExist (char *path)
|
||||||
|
{
|
||||||
|
DIR *dir;
|
||||||
|
|
||||||
|
dir=opendir(path);
|
||||||
|
if (dir)
|
||||||
|
{
|
||||||
|
closedir(dir);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool fsop_CopyFile (char *source, char *target, progress_callback_t spinner, void *spinner_data)
|
||||||
|
{
|
||||||
|
int err = 0;
|
||||||
|
fsop.breakop = 0;
|
||||||
|
|
||||||
|
u8 *buff = NULL;
|
||||||
|
u32 size;
|
||||||
|
u32 bytes, rb,wb;
|
||||||
|
u32 block = 71680; //70KB
|
||||||
|
FILE *fs = NULL, *ft = NULL;
|
||||||
|
|
||||||
|
fs = fopen(source, "rb");
|
||||||
|
if (!fs)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ft = fopen(target, "wt");
|
||||||
|
if (!ft)
|
||||||
|
{
|
||||||
|
SAFE_CLOSE(fs);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Get file size
|
||||||
|
fseek (fs, 0, SEEK_END);
|
||||||
|
size = ftell(fs);
|
||||||
|
|
||||||
|
fsop.size = size;
|
||||||
|
|
||||||
|
if (size == 0)
|
||||||
|
{
|
||||||
|
SAFE_CLOSE(fs);
|
||||||
|
SAFE_CLOSE(ft);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return to beginning....
|
||||||
|
fseek(fs, 0, SEEK_SET);
|
||||||
|
|
||||||
|
buff = MEM2_alloc(block);
|
||||||
|
if (buff == NULL)
|
||||||
|
{
|
||||||
|
SAFE_CLOSE(fs);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bytes = 0;
|
||||||
|
bool spinnerFlag = false;
|
||||||
|
if (strstr (source, "game.iso")) {
|
||||||
|
spinner(bytes, size, spinner_data);
|
||||||
|
spinnerFlag = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
rb = fread(buff, 1, block, fs);
|
||||||
|
wb = fwrite(buff, 1, rb, ft);
|
||||||
|
|
||||||
|
if (wb != wb) err = 1;
|
||||||
|
if (rb == 0) err = 1;
|
||||||
|
bytes += rb;
|
||||||
|
|
||||||
|
if (spinnerFlag) spinner(bytes, size, spinner_data);
|
||||||
|
|
||||||
|
fsop.multy.bytes += rb;
|
||||||
|
fsop.bytes = bytes;
|
||||||
|
|
||||||
|
if (fsop.breakop) break;
|
||||||
|
}
|
||||||
|
while (bytes < size && err == 0);
|
||||||
|
|
||||||
|
SAFE_CLOSE(fs);
|
||||||
|
SAFE_CLOSE(ft);
|
||||||
|
MEM2_free(buff);
|
||||||
|
|
||||||
|
if (err) unlink (target);
|
||||||
|
|
||||||
|
if (fsop.breakop || err) return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Semplified folder make
|
||||||
|
*/
|
||||||
|
int fsop_MakeFolder (char *path)
|
||||||
|
{
|
||||||
|
if (mkdir(path, S_IREAD | S_IWRITE) == 0) return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Recursive copyfolder
|
||||||
|
*/
|
||||||
|
static bool doCopyFolder (char *source, char *target, progress_callback_t spinner, void *spinner_data)
|
||||||
|
{
|
||||||
|
DIR *pdir;
|
||||||
|
struct dirent *pent;
|
||||||
|
char newSource[300], newTarget[300];
|
||||||
|
bool ret = true;
|
||||||
|
|
||||||
|
// If target folder doesn't exist, create it !
|
||||||
|
if (!fsop_DirExist (target))
|
||||||
|
{
|
||||||
|
fsop_MakeFolder (target);
|
||||||
|
}
|
||||||
|
|
||||||
|
pdir=opendir(source);
|
||||||
|
|
||||||
|
while ((pent=readdir(pdir)) != NULL && ret == true)
|
||||||
|
{
|
||||||
|
// Skip it
|
||||||
|
if (strcmp (pent->d_name, ".") == 0 || strcmp (pent->d_name, "..") == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
sprintf (newSource, "%s/%s", source, pent->d_name);
|
||||||
|
sprintf (newTarget, "%s/%s", target, pent->d_name);
|
||||||
|
|
||||||
|
// If it is a folder... recurse...
|
||||||
|
if (fsop_DirExist (newSource))
|
||||||
|
{
|
||||||
|
ret = doCopyFolder (newSource, newTarget, spinner, spinner_data);
|
||||||
|
}
|
||||||
|
else // It is a file !
|
||||||
|
{
|
||||||
|
strcpy (fsop.op, pent->d_name);
|
||||||
|
ret = fsop_CopyFile (newSource, newTarget, spinner, spinner_data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
closedir(pdir);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool fsop_CopyFolder (char *source, char *target, progress_callback_t spinner, void *spinner_data)
|
||||||
|
{
|
||||||
|
fsop.breakop = 0;
|
||||||
|
fsop.multy.startms = ticks_to_millisecs(gettime());
|
||||||
|
fsop.multy.bytes = 0;
|
||||||
|
fsop.multy.size = fsop_GetFolderBytes (source);
|
||||||
|
|
||||||
|
return doCopyFolder (source, target, spinner, spinner_data);
|
||||||
|
}
|
46
source/gc/fileOps.h
Normal file
46
source/gc/fileOps.h
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef _FILEOPS
|
||||||
|
#define _FILEOPS
|
||||||
|
|
||||||
|
typedef void (*progress_callback_t)(int status,int total,void *user_data);
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
u64 size, bytes; // for operation that uses more than one file
|
||||||
|
u32 startms;
|
||||||
|
}
|
||||||
|
s_fsopmulty;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
char op[256]; // Calling process can set filename or any other info that fit
|
||||||
|
|
||||||
|
u32 size, bytes;
|
||||||
|
|
||||||
|
s_fsopmulty multy;
|
||||||
|
|
||||||
|
int flag1; // user defined flag
|
||||||
|
bool breakop; // allow to stop a long operation
|
||||||
|
}
|
||||||
|
s_fsop;
|
||||||
|
|
||||||
|
extern s_fsop fsop;
|
||||||
|
|
||||||
|
bool fsop_GetFileSizeBytes (char *path, size_t *filesize);
|
||||||
|
u64 fsop_GetFolderBytes (char *source);
|
||||||
|
u32 fsop_GetFolderKb (char *source);
|
||||||
|
u32 fsop_GetFreeSpaceKb (char *path);
|
||||||
|
bool fsop_DirExist (char *path);
|
||||||
|
bool fsop_CopyFile (char *source, char *target, progress_callback_t spinner, void *spinner_data);
|
||||||
|
int fsop_MakeFolder (char *path);
|
||||||
|
bool fsop_CopyFolder (char *source, char *target, progress_callback_t spinner, void *spinner_data);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
@ -4,6 +4,7 @@
|
|||||||
#include <dirent.h>
|
#include <dirent.h>
|
||||||
#include "gc.h"
|
#include "gc.h"
|
||||||
#include "gecko.h"
|
#include "gecko.h"
|
||||||
|
#include "fileOps.h"
|
||||||
|
|
||||||
#define MAX_FAT_PATH 1024
|
#define MAX_FAT_PATH 1024
|
||||||
|
|
||||||
@ -94,18 +95,18 @@ void set_language(u8 lang)
|
|||||||
while(!__SYS_SyncSram());
|
while(!__SYS_SyncSram());
|
||||||
}
|
}
|
||||||
|
|
||||||
void DML_RemoveGame(const char *discid)
|
void DML_RemoveGame(const char *discid, const char* partition)
|
||||||
{
|
{
|
||||||
int num = 6;
|
int num = 6;
|
||||||
const char *fl[6] = {"sd:/games/%s/game.iso","sd:/games/%s/sys/boot.bin","sd:/games/%s/sys/bi2.bin",
|
const char *fl[6] = {"%s:/games/%s/game.iso","%s:/games/%s/sys/boot.bin","%s:/games/%s/sys/bi2.bin",
|
||||||
"sd:/games/%s/sys/apploader.img","sd:/games/%s/sys","sd:/games/%s"};
|
"%s:/games/%s/sys/apploader.img","%s:/games/%s/sys","%s:/games/%s"};
|
||||||
char fname[MAX_FAT_PATH];
|
char fname[MAX_FAT_PATH];
|
||||||
FILE *f;
|
FILE *f;
|
||||||
DIR *dir;
|
DIR *dir;
|
||||||
int i;
|
int i;
|
||||||
for(i = 0; i < num; i++)
|
for(i = 0; i < num; i++)
|
||||||
{
|
{
|
||||||
sprintf(fname, fl[i], discid);
|
sprintf(fname, fl[i], partition, discid);
|
||||||
f = fopen((char*)fname, "r");
|
f = fopen((char*)fname, "r");
|
||||||
if(f)
|
if(f)
|
||||||
{
|
{
|
||||||
@ -123,10 +124,10 @@ void DML_RemoveGame(const char *discid)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DML_GameIsInstalled(char *discid)
|
bool DML_GameIsInstalled(char *discid, const char* partition)
|
||||||
{
|
{
|
||||||
char filepath[64];
|
char filepath[64];
|
||||||
sprintf(filepath, "sd:/games/%s/game.iso", discid);
|
sprintf(filepath, "%s:/games/%s/game.iso", partition, discid);
|
||||||
|
|
||||||
gprintf("Filepath on SD: %s\n", filepath);
|
gprintf("Filepath on SD: %s\n", filepath);
|
||||||
|
|
||||||
|
@ -7,8 +7,8 @@ extern "C"
|
|||||||
#define GC_H_
|
#define GC_H_
|
||||||
void set_video_mode(int i);
|
void set_video_mode(int i);
|
||||||
void set_language(u8 lang);
|
void set_language(u8 lang);
|
||||||
void DML_RemoveGame(const char *discid);
|
void DML_RemoveGame(const char *discid, const char* partition);
|
||||||
bool DML_GameIsInstalled(char *discid);
|
bool DML_GameIsInstalled(char *discid, const char* partition);
|
||||||
#endif //GC_H_
|
#endif //GC_H_
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
@ -131,7 +131,7 @@ void CList<dir_discHdr>::GetHeaders(safe_vector<string> pathlist, safe_vector<di
|
|||||||
if (wbfs || (*itr).rfind(".iso") != string::npos || (*itr).rfind(".ISO") != string::npos)
|
if (wbfs || (*itr).rfind(".iso") != string::npos || (*itr).rfind(".ISO") != string::npos)
|
||||||
{
|
{
|
||||||
char* filename = &(*itr)[(*itr).find_last_of('/')+1];
|
char* filename = &(*itr)[(*itr).find_last_of('/')+1];
|
||||||
if(strcasecmp(filename, "game.iso") == 0 && strncasecmp((*itr).c_str(), "sd:/games/", 10) == 0 )
|
if(strcasecmp(filename, "game.iso") == 0 && strstr((*itr).c_str(), ":/games/") != NULL)
|
||||||
{
|
{
|
||||||
FILE *fp = fopen((*itr).c_str(), "rb");
|
FILE *fp = fopen((*itr).c_str(), "rb");
|
||||||
if( fp )
|
if( fp )
|
||||||
|
@ -175,12 +175,12 @@ s32 GCDump::DumpGame(progress_callback_t spinner, void *spinner_data)
|
|||||||
s32 ret = Disc_ReadGCHeader(&gcheader);
|
s32 ret = Disc_ReadGCHeader(&gcheader);
|
||||||
Asciify2(gcheader.title);
|
Asciify2(gcheader.title);
|
||||||
|
|
||||||
snprintf(folder, sizeof(folder), "%s:/games/%s [%s]", DeviceName[SD], gcheader.title, (char *)gcheader.id);
|
snprintf(folder, sizeof(folder), "%s:/games/%s [%s]", gamepartition, gcheader.title, (char *)gcheader.id);
|
||||||
makedir((char *)folder);
|
makedir((char *)folder);
|
||||||
|
|
||||||
if(writeexfiles)
|
if(writeexfiles)
|
||||||
{
|
{
|
||||||
snprintf(folder, sizeof(folder), "%s:/games/%s [%s]/sys", DeviceName[SD], gcheader.title, (char *)gcheader.id);
|
snprintf(folder, sizeof(folder), "%s:/games/%s [%s]/sys", gamepartition, gcheader.title, (char *)gcheader.id);
|
||||||
makedir((char *)folder);
|
makedir((char *)folder);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -240,7 +240,7 @@ s32 GCDump::DumpGame(progress_callback_t spinner, void *spinner_data)
|
|||||||
__DiscWrite(gamepath, 0x2440, ApploaderSize, spinner, spinner_data);
|
__DiscWrite(gamepath, 0x2440, ApploaderSize, spinner, spinner_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
snprintf(gamepath, sizeof(gamepath), "%s:/games/%s [%s]/game.iso", DeviceName[SD], gcheader.title, (char *)gcheader.id);
|
snprintf(gamepath, sizeof(gamepath), "%s:/games/%s [%s]/game.iso", gamepartition, gcheader.title, (char *)gcheader.id);
|
||||||
|
|
||||||
gprintf("Writing %s\n", gamepath);
|
gprintf("Writing %s\n", gamepath);
|
||||||
if(compressed)
|
if(compressed)
|
||||||
@ -389,6 +389,6 @@ s32 GCDump::CheckSpace(u32 *needed, bool comp)
|
|||||||
MEM2_free(FSTBuffer);
|
MEM2_free(FSTBuffer);
|
||||||
}
|
}
|
||||||
*needed = size/0x8000;
|
*needed = size/0x8000;
|
||||||
gprintf("Free space needed on SD: %d bytes (%x blocks)\n", size, size/0x8000);
|
gprintf("Free space needed: %d bytes (%x blocks)\n", size, size/0x8000);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
@ -33,7 +33,7 @@ typedef void (*progress_callback_t)(int status,int total,void *user_data);
|
|||||||
class GCDump
|
class GCDump
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
void Init(bool skip, bool comp, bool wexf, bool align, u32 nretry, u32 rsize)
|
void Init(bool skip, bool comp, bool wexf, bool align, u32 nretry, u32 rsize, const char* partition)
|
||||||
{
|
{
|
||||||
skiponerror = skip;
|
skiponerror = skip;
|
||||||
compressed = comp;
|
compressed = comp;
|
||||||
@ -41,6 +41,7 @@ public:
|
|||||||
force_32k_align = align;
|
force_32k_align = align;
|
||||||
gc_nbrretry = nretry;
|
gc_nbrretry = nretry;
|
||||||
gc_readsize = rsize;
|
gc_readsize = rsize;
|
||||||
|
gamepartition = partition;
|
||||||
gc_skipped = 0;
|
gc_skipped = 0;
|
||||||
}
|
}
|
||||||
s32 DumpGame(progress_callback_t spinner, void *spinner_data);
|
s32 DumpGame(progress_callback_t spinner, void *spinner_data);
|
||||||
@ -50,6 +51,7 @@ private:
|
|||||||
bool skiponerror;
|
bool skiponerror;
|
||||||
bool compressed;
|
bool compressed;
|
||||||
bool writeexfiles;
|
bool writeexfiles;
|
||||||
|
const char* gamepartition;
|
||||||
u32 gc_nbrretry;
|
u32 gc_nbrretry;
|
||||||
u32 gc_error;
|
u32 gc_error;
|
||||||
u32 gc_retry;
|
u32 gc_retry;
|
||||||
|
@ -135,6 +135,7 @@ CMenu::CMenu(CVideo &vid) :
|
|||||||
m_gamesound_changed = false;
|
m_gamesound_changed = false;
|
||||||
m_base_font_size = 0;
|
m_base_font_size = 0;
|
||||||
m_current_view = COVERFLOW_USB;
|
m_current_view = COVERFLOW_USB;
|
||||||
|
copyGameCubeGame = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" { int makedir(char *newdir); }
|
extern "C" { int makedir(char *newdir); }
|
||||||
@ -1876,12 +1877,13 @@ bool CMenu::_loadHomebrewList()
|
|||||||
|
|
||||||
bool CMenu::_loadDmlList()
|
bool CMenu::_loadDmlList()
|
||||||
{
|
{
|
||||||
if(!DeviceHandler::Instance()->IsInserted(SD))
|
currentPartition = m_cfg.getInt("DML", "partition", 0);
|
||||||
|
if(!DeviceHandler::Instance()->IsInserted(currentPartition))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
gprintf("%s\n", DeviceName[SD]);
|
gprintf("%s\n", DeviceName[currentPartition]);
|
||||||
DeviceHandler::Instance()->Open_WBFS(SD);
|
DeviceHandler::Instance()->Open_WBFS(currentPartition);
|
||||||
m_gameList.Load(sfmt(DML_DIR, DeviceName[SD]), ".iso", m_cfg.getString("DML", "lastlanguage", "EN").c_str());
|
m_gameList.Load(sfmt(DML_DIR, DeviceName[currentPartition]), ".iso", m_cfg.getString("DML", "lastlanguage", "EN").c_str());
|
||||||
m_cfg.setString("DML", "lastlanguage", m_loc.getString(m_curLanguage, "gametdb_code", "EN"));
|
m_cfg.setString("DML", "lastlanguage", m_loc.getString(m_curLanguage, "gametdb_code", "EN"));
|
||||||
m_cfg.save();
|
m_cfg.save();
|
||||||
return m_gameList.size() > 0 ? true : false;
|
return m_gameList.size() > 0 ? true : false;
|
||||||
|
@ -634,6 +634,7 @@ private:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
enum WBFS_OP { WO_ADD_GAME, WO_REMOVE_GAME, WO_FORMAT };
|
enum WBFS_OP { WO_ADD_GAME, WO_REMOVE_GAME, WO_FORMAT };
|
||||||
|
bool copyGameCubeGame;
|
||||||
typedef std::pair<std::string, u32> FontDesc;
|
typedef std::pair<std::string, u32> FontDesc;
|
||||||
typedef std::map<FontDesc, SFont> FontSet;
|
typedef std::map<FontDesc, SFont> FontSet;
|
||||||
typedef std::map<std::string, STexture> TexSet;
|
typedef std::map<std::string, STexture> TexSet;
|
||||||
@ -931,6 +932,7 @@ private:
|
|||||||
static void _addDiscProgress(int status, int total, void *user_data);
|
static void _addDiscProgress(int status, int total, void *user_data);
|
||||||
static int _gameInstaller(void *obj);
|
static int _gameInstaller(void *obj);
|
||||||
static int _GCgameInstaller(void *obj);
|
static int _GCgameInstaller(void *obj);
|
||||||
|
static int _GCcopyGame(void *obj);
|
||||||
wstringEx _optBoolToString(int b);
|
wstringEx _optBoolToString(int b);
|
||||||
void _stopSounds(void);
|
void _stopSounds(void);
|
||||||
|
|
||||||
|
@ -84,14 +84,12 @@ void CMenu::_showConfig(void)
|
|||||||
_setBg(m_configBg, m_configBg);
|
_setBg(m_configBg, m_configBg);
|
||||||
m_btnMgr.show(m_configLblTitle);
|
m_btnMgr.show(m_configLblTitle);
|
||||||
m_btnMgr.show(m_configBtnBack);
|
m_btnMgr.show(m_configBtnBack);
|
||||||
if (m_current_view != COVERFLOW_DML && !m_locked)
|
if (!m_locked)
|
||||||
{
|
{
|
||||||
m_btnMgr.show(m_configLblPartitionName);
|
m_btnMgr.show(m_configLblPartitionName);
|
||||||
m_btnMgr.show(m_configLblPartition);
|
m_btnMgr.show(m_configLblPartition);
|
||||||
m_btnMgr.show(m_configBtnPartitionP);
|
m_btnMgr.show(m_configBtnPartitionP);
|
||||||
m_btnMgr.show(m_configBtnPartitionM);
|
m_btnMgr.show(m_configBtnPartitionM);
|
||||||
}
|
|
||||||
if (!m_locked) {
|
|
||||||
m_btnMgr.show(m_configLblDownload);
|
m_btnMgr.show(m_configLblDownload);
|
||||||
m_btnMgr.show(m_configBtnDownload);
|
m_btnMgr.show(m_configBtnDownload);
|
||||||
}
|
}
|
||||||
|
@ -161,8 +161,6 @@ void CMenu::_showGameSettings(void)
|
|||||||
|
|
||||||
if(m_current_view != COVERFLOW_DML)
|
if(m_current_view != COVERFLOW_DML)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
m_btnMgr.hide(m_gameSettingsBtnCategoryMain);
|
m_btnMgr.hide(m_gameSettingsBtnCategoryMain);
|
||||||
m_btnMgr.hide(m_gameSettingsLblCategoryMain);
|
m_btnMgr.hide(m_gameSettingsLblCategoryMain);
|
||||||
|
|
||||||
|
@ -424,6 +424,19 @@ void CMenu::_game(bool launch)
|
|||||||
else if (launch || m_btnMgr.selected(m_gameBtnPlay) || (!WPadIR_Valid(0) && !WPadIR_Valid(1) && !WPadIR_Valid(2) && !WPadIR_Valid(3) && m_btnMgr.selected((u32)-1)))
|
else if (launch || m_btnMgr.selected(m_gameBtnPlay) || (!WPadIR_Valid(0) && !WPadIR_Valid(1) && !WPadIR_Valid(2) && !WPadIR_Valid(3) && m_btnMgr.selected((u32)-1)))
|
||||||
{
|
{
|
||||||
_hideGame();
|
_hideGame();
|
||||||
|
|
||||||
|
if(currentPartition != SD && m_current_view == COVERFLOW_DML)
|
||||||
|
{
|
||||||
|
copyGameCubeGame = true;
|
||||||
|
if(!_wbfsOp(CMenu::WO_ADD_GAME))
|
||||||
|
{
|
||||||
|
copyGameCubeGame = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
currentPartition = SD;
|
||||||
|
}
|
||||||
|
|
||||||
|
copyGameCubeGame = false;
|
||||||
dir_discHdr *hdr = m_cf.getHdr();
|
dir_discHdr *hdr = m_cf.getHdr();
|
||||||
|
|
||||||
m_cf.clear();
|
m_cf.clear();
|
||||||
|
@ -156,13 +156,15 @@ void CMenu::LoadView(void)
|
|||||||
m_cf.applySettings();
|
m_cf.applySettings();
|
||||||
|
|
||||||
char *mode = (m_current_view == COVERFLOW_CHANNEL && m_cfg.getBool("NAND", "disable", true))
|
char *mode = (m_current_view == COVERFLOW_CHANNEL && m_cfg.getBool("NAND", "disable", true))
|
||||||
? (char *)"NAND" : ((m_current_view == COVERFLOW_DML) ? (char *)"DML" : (char *)DeviceName[currentPartition]);
|
? (char *)"NAND" : (char *)DeviceName[currentPartition];
|
||||||
|
|
||||||
for(u8 i = 0; strncmp((const char *)&mode[i], "\0", 1) != 0; i++)
|
for(u8 i = 0; strncmp((const char *)&mode[i], "\0", 1) != 0; i++)
|
||||||
mode[i] = toupper(mode[i]);
|
mode[i] = toupper(mode[i]);
|
||||||
|
|
||||||
m_showtimer=60;
|
m_showtimer=60;
|
||||||
m_btnMgr.setText(m_mainLblNotice, (string)mode);
|
char gui_name[20];
|
||||||
|
sprintf(gui_name,"%s [%s]",_domainFromView(),mode);
|
||||||
|
m_btnMgr.setText(m_mainLblNotice, (string)gui_name);
|
||||||
m_btnMgr.show(m_mainLblNotice);
|
m_btnMgr.show(m_mainLblNotice);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -370,7 +372,7 @@ int CMenu::main(void)
|
|||||||
{
|
{
|
||||||
bool block = m_current_view == COVERFLOW_CHANNEL && m_cfg.getBool("NAND", "disable", true);
|
bool block = m_current_view == COVERFLOW_CHANNEL && m_cfg.getBool("NAND", "disable", true);
|
||||||
char *partition;
|
char *partition;
|
||||||
if(!block && (m_current_view != COVERFLOW_DML))
|
if(!block)
|
||||||
{
|
{
|
||||||
_showWaitMessage();
|
_showWaitMessage();
|
||||||
_hideMain();
|
_hideMain();
|
||||||
@ -387,7 +389,7 @@ int CMenu::main(void)
|
|||||||
(m_current_view == COVERFLOW_CHANNEL && (DeviceHandler::Instance()->GetFSType(currentPartition) != PART_FS_FAT ||
|
(m_current_view == COVERFLOW_CHANNEL && (DeviceHandler::Instance()->GetFSType(currentPartition) != PART_FS_FAT ||
|
||||||
(!isD2XnewerThanV6 && DeviceHandler::Instance()->PathToDriveType(m_appDir.c_str()) == currentPartition) ||
|
(!isD2XnewerThanV6 && DeviceHandler::Instance()->PathToDriveType(m_appDir.c_str()) == currentPartition) ||
|
||||||
(!isD2XnewerThanV6 && DeviceHandler::Instance()->PathToDriveType(m_dataDir.c_str()) == currentPartition))) ||
|
(!isD2XnewerThanV6 && DeviceHandler::Instance()->PathToDriveType(m_dataDir.c_str()) == currentPartition))) ||
|
||||||
(m_current_view == COVERFLOW_HOMEBREW && DeviceHandler::Instance()->GetFSType(currentPartition) == PART_FS_WBFS))
|
((m_current_view == COVERFLOW_HOMEBREW || m_current_view == COVERFLOW_DML) && DeviceHandler::Instance()->GetFSType(currentPartition) == PART_FS_WBFS))
|
||||||
{
|
{
|
||||||
currentPartition = loopNum(currentPartition + 1, (int)USB8);
|
currentPartition = loopNum(currentPartition + 1, (int)USB8);
|
||||||
if(limiter > 10) break;
|
if(limiter > 10) break;
|
||||||
@ -399,8 +401,6 @@ int CMenu::main(void)
|
|||||||
m_cfg.setInt(_domainFromView(), "partition", currentPartition);
|
m_cfg.setInt(_domainFromView(), "partition", currentPartition);
|
||||||
|
|
||||||
}
|
}
|
||||||
else if (m_current_view == COVERFLOW_DML)
|
|
||||||
partition = (char *)"DML";
|
|
||||||
else
|
else
|
||||||
partition = (char *)"NAND";
|
partition = (char *)"NAND";
|
||||||
|
|
||||||
@ -410,10 +410,12 @@ int CMenu::main(void)
|
|||||||
gprintf("Next item: %s\n", partition);
|
gprintf("Next item: %s\n", partition);
|
||||||
|
|
||||||
m_showtimer=60;
|
m_showtimer=60;
|
||||||
m_btnMgr.setText(m_mainLblNotice, (string)partition);
|
char gui_name[20];
|
||||||
|
sprintf(gui_name,"%s [%s]",_domainFromView(),partition);
|
||||||
|
m_btnMgr.setText(m_mainLblNotice, (string)gui_name);
|
||||||
m_btnMgr.show(m_mainLblNotice);
|
m_btnMgr.show(m_mainLblNotice);
|
||||||
|
|
||||||
if(!block && (m_current_view != COVERFLOW_DML))
|
if(!block)
|
||||||
{
|
{
|
||||||
_loadList();
|
_loadList();
|
||||||
_showMain();
|
_showMain();
|
||||||
|
@ -4,6 +4,9 @@
|
|||||||
#include "lockMutex.hpp"
|
#include "lockMutex.hpp"
|
||||||
#include "loader/gc_disc.hpp"
|
#include "loader/gc_disc.hpp"
|
||||||
#include "gc.h"
|
#include "gc.h"
|
||||||
|
#include "fileOps.h"
|
||||||
|
#include "music/SoundHandler.hpp"
|
||||||
|
#include "channel/nand.hpp"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
@ -119,19 +122,21 @@ int CMenu::_GCgameInstaller(void *obj)
|
|||||||
u32 nretry = m.m_cfg.getUInt("DML", "num_retries", 5);
|
u32 nretry = m.m_cfg.getUInt("DML", "num_retries", 5);
|
||||||
u32 rsize = 32768;
|
u32 rsize = 32768;
|
||||||
|
|
||||||
m_gcdump.Init(skip, comp, wexf, alig, nretry, rsize);
|
m_gcdump.Init(skip, comp, wexf, alig, nretry, rsize,DeviceName[currentPartition]);
|
||||||
|
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (!DeviceHandler::Instance()->IsInserted(SD))
|
if (!DeviceHandler::Instance()->IsInserted(currentPartition))
|
||||||
{
|
{
|
||||||
m.m_thrdWorking = false;
|
m.m_thrdWorking = false;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char partition[strlen(DeviceName[currentPartition])+2];
|
||||||
|
sprintf(partition,"%s:/",DeviceName[currentPartition]);
|
||||||
struct statvfs stats;
|
struct statvfs stats;
|
||||||
memset(&stats, 0, sizeof(stats));
|
memset(&stats, 0, sizeof(stats));
|
||||||
statvfs("sd:/" , &stats);
|
statvfs(partition , &stats);
|
||||||
|
|
||||||
u64 free = (u64)stats.f_frsize * (u64)stats.f_bfree;
|
u64 free = (u64)stats.f_frsize * (u64)stats.f_bfree;
|
||||||
u32 needed = 0;
|
u32 needed = 0;
|
||||||
@ -170,6 +175,45 @@ int CMenu::_GCgameInstaller(void *obj)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int CMenu::_GCcopyGame(void *obj)
|
||||||
|
{
|
||||||
|
CMenu &m = *(CMenu *)obj;
|
||||||
|
char partition[strlen(DeviceName[SD])];
|
||||||
|
sprintf(partition,"%s:/",DeviceName[SD]);
|
||||||
|
if(fsop_GetFreeSpaceKb((char*)DeviceName[SD])<fsop_GetFolderKb(m.m_cf.getHdr()->path))
|
||||||
|
{
|
||||||
|
LWP_MutexLock(m.m_mutex);
|
||||||
|
m._setThrdMsg(wfmt(m._fmt("wbfsop11", L"Not enough space: %d blocks needed, %d available"), fsop_GetFolderKb(m.m_cf.getHdr()->path), fsop_GetFreeSpaceKb(partition)), 0.f);
|
||||||
|
LWP_MutexUnlock(m.m_mutex);
|
||||||
|
m.m_thrdWorking = false;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LWP_MutexLock(m.m_mutex);
|
||||||
|
m._setThrdMsg(L"", 0);
|
||||||
|
char folder[10] = "sd:/games";
|
||||||
|
if (!fsop_DirExist(folder))
|
||||||
|
{
|
||||||
|
fsop_MakeFolder(folder);
|
||||||
|
}
|
||||||
|
char source[64];
|
||||||
|
char target[64];
|
||||||
|
sprintf(source, "%s:/games/%s", DeviceName[currentPartition], m.m_cf.getHdr()->path);
|
||||||
|
sprintf(target, "sd:/games/%s", m.m_cf.getHdr()->path);
|
||||||
|
gprintf("Copying from: \n%s \nto: \n%s\n",source,target);
|
||||||
|
LWP_MutexUnlock(m.m_mutex);
|
||||||
|
fsop_CopyFolder(source, target, CMenu::_addDiscProgress, obj);
|
||||||
|
LWP_MutexLock(m.m_mutex);
|
||||||
|
m._setThrdMsg(m._t("wbfsop12", L"Game copied"), 1.f);
|
||||||
|
gprintf("Game copied.\n");
|
||||||
|
LWP_MutexUnlock(m.m_mutex);
|
||||||
|
slotLight(true);
|
||||||
|
}
|
||||||
|
m.m_thrdWorking = false;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
bool CMenu::_wbfsOp(CMenu::WBFS_OP op)
|
bool CMenu::_wbfsOp(CMenu::WBFS_OP op)
|
||||||
{
|
{
|
||||||
lwp_t thread = 0;
|
lwp_t thread = 0;
|
||||||
@ -188,10 +232,13 @@ bool CMenu::_wbfsOp(CMenu::WBFS_OP op)
|
|||||||
switch (op)
|
switch (op)
|
||||||
{
|
{
|
||||||
case CMenu::WO_ADD_GAME:
|
case CMenu::WO_ADD_GAME:
|
||||||
|
if(copyGameCubeGame)
|
||||||
|
m_btnMgr.setText(m_wbfsLblDialog, _t("wbfscpydlg", L"If you are sure you want to copy this game to SD, click on Go."));
|
||||||
|
else
|
||||||
m_btnMgr.setText(m_wbfsLblDialog, _t("wbfsadddlg", L"Please insert the disc you want to copy, then click on Go."));
|
m_btnMgr.setText(m_wbfsLblDialog, _t("wbfsadddlg", L"Please insert the disc you want to copy, then click on Go."));
|
||||||
break;
|
break;
|
||||||
case CMenu::WO_REMOVE_GAME:
|
case CMenu::WO_REMOVE_GAME:
|
||||||
m_btnMgr.setText(m_wbfsLblDialog, wfmt(_fmt("wbfsremdlg", L"To permanently remove the game : %s, click on Go."), m_cf.getTitle().c_str()));
|
m_btnMgr.setText(m_wbfsLblDialog, wfmt(_fmt("wbfsremdlg", L"To permanently remove the game: %s, click on Go."), (u8*)m_cf.getTitle().toUTF8().c_str()));
|
||||||
break;
|
break;
|
||||||
case CMenu::WO_FORMAT:
|
case CMenu::WO_FORMAT:
|
||||||
break;
|
break;
|
||||||
@ -202,7 +249,11 @@ bool CMenu::_wbfsOp(CMenu::WBFS_OP op)
|
|||||||
{
|
{
|
||||||
_mainLoopCommon(false, m_thrdWorking);
|
_mainLoopCommon(false, m_thrdWorking);
|
||||||
if ((BTN_HOME_PRESSED || BTN_B_PRESSED) && !m_thrdWorking)
|
if ((BTN_HOME_PRESSED || BTN_B_PRESSED) && !m_thrdWorking)
|
||||||
|
{
|
||||||
|
if (copyGameCubeGame)
|
||||||
|
return done;
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
else if (BTN_UP_PRESSED)
|
else if (BTN_UP_PRESSED)
|
||||||
m_btnMgr.up();
|
m_btnMgr.up();
|
||||||
else if (BTN_DOWN_PRESSED)
|
else if (BTN_DOWN_PRESSED)
|
||||||
@ -210,7 +261,11 @@ bool CMenu::_wbfsOp(CMenu::WBFS_OP op)
|
|||||||
if (BTN_A_PRESSED && !m_thrdWorking)
|
if (BTN_A_PRESSED && !m_thrdWorking)
|
||||||
{
|
{
|
||||||
if (m_btnMgr.selected(m_wbfsBtnBack))
|
if (m_btnMgr.selected(m_wbfsBtnBack))
|
||||||
|
{
|
||||||
|
if (copyGameCubeGame)
|
||||||
|
return done;
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
else if (m_btnMgr.selected(m_wbfsBtnGo))
|
else if (m_btnMgr.selected(m_wbfsBtnGo))
|
||||||
{
|
{
|
||||||
switch (op)
|
switch (op)
|
||||||
@ -222,6 +277,34 @@ bool CMenu::_wbfsOp(CMenu::WBFS_OP op)
|
|||||||
m_btnMgr.hide(m_wbfsBtnBack);
|
m_btnMgr.hide(m_wbfsBtnBack);
|
||||||
m_btnMgr.show(m_wbfsLblMessage);
|
m_btnMgr.show(m_wbfsLblMessage);
|
||||||
m_btnMgr.setText(m_wbfsLblMessage, L"");
|
m_btnMgr.setText(m_wbfsLblMessage, L"");
|
||||||
|
if (copyGameCubeGame)
|
||||||
|
{
|
||||||
|
char gcfolder[64];
|
||||||
|
char* title = (char *)m_cf.getTitle().toUTF8().c_str();
|
||||||
|
char* gameid = (char *)m_cf.getHdr()->hdr.id;
|
||||||
|
sprintf(gcfolder, "%s [%s]", title, gameid);
|
||||||
|
if (DML_GameIsInstalled(gameid, DeviceName[SD]) || DML_GameIsInstalled(gcfolder, DeviceName[SD]))
|
||||||
|
{
|
||||||
|
error(_t("wbfsoperr4", L"Game already installed"));
|
||||||
|
out = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
cfPos = string(gameid);
|
||||||
|
m_btnMgr.setText(m_wbfsLblDialog, wfmt(_fmt("wbfsop10", L"Copying [%s] %s..."), (u8*)gameid, (u8*)m_cf.getTitle().toUTF8().c_str()));
|
||||||
|
done = true;
|
||||||
|
m_thrdWorking = true;
|
||||||
|
m_thrdProgress = 0.f;
|
||||||
|
m_thrdMessageAdded = false;
|
||||||
|
m_cf.stopCoverLoader();
|
||||||
|
_stopSounds();
|
||||||
|
MusicPlayer::DestroyInstance();
|
||||||
|
SoundHandler::DestroyInstance();
|
||||||
|
soundDeinit();
|
||||||
|
Nand::Instance()->Disable_Emu();
|
||||||
|
Nand::DestroyInstance();
|
||||||
|
LWP_CreateThread(&thread, (void *(*)(void *))CMenu::_GCcopyGame, (void *)this, 0, 8 * 1024, 64);
|
||||||
|
break;
|
||||||
|
}
|
||||||
Disc_SetUSB(NULL);
|
Disc_SetUSB(NULL);
|
||||||
if (Disc_Wait() < 0)
|
if (Disc_Wait() < 0)
|
||||||
{
|
{
|
||||||
@ -260,7 +343,7 @@ bool CMenu::_wbfsOp(CMenu::WBFS_OP op)
|
|||||||
|
|
||||||
char gcfolder[64];
|
char gcfolder[64];
|
||||||
sprintf(gcfolder, "%s [%s]", gcheader.title, (char *)gcheader.id);
|
sprintf(gcfolder, "%s [%s]", gcheader.title, (char *)gcheader.id);
|
||||||
if (_searchGamesByID((const char *) gcheader.id).size() != 0 || DML_GameIsInstalled((char *)gcheader.id) || DML_GameIsInstalled(gcfolder))
|
if (_searchGamesByID((const char *) gcheader.id).size() != 0 || DML_GameIsInstalled((char *)gcheader.id, DeviceName[currentPartition]) || DML_GameIsInstalled(gcfolder, DeviceName[currentPartition]))
|
||||||
{
|
{
|
||||||
error(_t("wbfsoperr4", L"Game already installed"));
|
error(_t("wbfsoperr4", L"Game already installed"));
|
||||||
out = true;
|
out = true;
|
||||||
@ -286,7 +369,7 @@ bool CMenu::_wbfsOp(CMenu::WBFS_OP op)
|
|||||||
if(m_current_view == COVERFLOW_USB)
|
if(m_current_view == COVERFLOW_USB)
|
||||||
WBFS_RemoveGame((u8 *)m_cf.getId().c_str(), (char *) m_cf.getHdr()->path);
|
WBFS_RemoveGame((u8 *)m_cf.getId().c_str(), (char *) m_cf.getHdr()->path);
|
||||||
else
|
else
|
||||||
DML_RemoveGame(m_cf.getHdr()->path);
|
DML_RemoveGame(m_cf.getHdr()->path, DeviceName[currentPartition]);
|
||||||
if(m_cfg.getBool("GENERAL", "delete_cover_and_game", true))
|
if(m_cfg.getBool("GENERAL", "delete_cover_and_game", true))
|
||||||
RemoveCover((char *)m_cf.getId().c_str());
|
RemoveCover((char *)m_cf.getId().c_str());
|
||||||
m_btnMgr.show(m_wbfsPBar);
|
m_btnMgr.show(m_wbfsPBar);
|
||||||
@ -319,7 +402,7 @@ bool CMenu::_wbfsOp(CMenu::WBFS_OP op)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
_hideWBFS();
|
_hideWBFS();
|
||||||
if (done && (op == CMenu::WO_REMOVE_GAME || op == CMenu::WO_ADD_GAME))
|
if (done && !copyGameCubeGame && (op == CMenu::WO_REMOVE_GAME || op == CMenu::WO_ADD_GAME))
|
||||||
{
|
{
|
||||||
m_gameList.SetLanguage(m_loc.getString(m_curLanguage, "gametdb_code", "EN").c_str());
|
m_gameList.SetLanguage(m_loc.getString(m_curLanguage, "gametdb_code", "EN").c_str());
|
||||||
if( upd_dml )
|
if( upd_dml )
|
||||||
|
Loading…
Reference in New Issue
Block a user