-updated dml usb to sd installer, should

be faster now thanks to threaded copy by
stfour, also fixed codedumps when copying
from ntfs to sd, everything should work now
This commit is contained in:
fix94.1 2012-03-03 17:16:11 +00:00
parent 5e18be6598
commit fcf9d344f7
6 changed files with 136 additions and 104 deletions

View File

@ -20,15 +20,25 @@ en exposed s_fsop fsop structure can be used by callback to update operation sta
#include "fileOps.h"
#include "memory/mem2.hpp"
#include "utils.h"
#include "gecko.h"
s_fsop fsop;
#define SET(a, b) a = b; DCFlushRange(&a, sizeof(a));
#define STACKSIZE 8192
static u8 *buff = NULL;
static FILE *fs = NULL, *ft = NULL;
static u32 block = 32768;
static u32 blockIdx = 0;
static u32 blockInfo[2] = {0,0};
static u32 blockReady = 0;
static u32 stopThread;
// 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)
{
@ -42,7 +52,6 @@ bool fsop_GetFileSizeBytes (char *path, size_t *filesize) // for me stats st_siz
if (filesize) *filesize = size;
SAFE_CLOSE(f);
return true;
}
@ -55,17 +64,17 @@ u64 fsop_GetFolderBytes (char *source)
struct dirent *pent;
char newSource[300];
u64 bytes = 0;
pdir=opendir(source);
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))
{
@ -78,13 +87,10 @@ u64 fsop_GetFolderBytes (char *source)
bytes += s;
}
}
closedir(pdir);
//Debug ("fsop_GetFolderBytes (%s) = %llu", source, bytes);
return bytes;
}
}
u32 fsop_GetFolderKb (char *source)
{
@ -96,11 +102,11 @@ u32 fsop_GetFolderKb (char *source)
u32 fsop_GetFreeSpaceKb (char *path) // Return free kb on the device passed
{
struct statvfs s;
statvfs (path, &s);
statvfs(path, &s);
u32 ret = (u32)round( ((double)s.f_bfree / 1000.0) * s.f_bsize);
return ret ;
}
@ -108,28 +114,46 @@ u32 fsop_GetFreeSpaceKb (char *path) // Return free kb on the device passed
bool fsop_DirExist (char *path)
{
DIR *dir;
dir=opendir(path);
if (dir)
{
closedir(dir);
return true;
}
return false;
}
static void *thread_CopyFileReader (void *arg)
{
u32 rb;
stopThread = 0;
DCFlushRange(&stopThread, sizeof(stopThread));
do
{
SET (rb, fread(&buff[blockIdx*block], 1, block, fs ));
SET (blockInfo[blockIdx], rb);
SET (blockReady, 1);
while (blockReady && !stopThread) usleep(1);
}
while (stopThread == 0);
stopThread = -1;
DCFlushRange(&stopThread, sizeof(stopThread));
return 0;
}
bool fsop_CopyFile (char *source, char *target, progress_callback_t spinner, void *spinner_data)
{
gprintf("Creating file: %s\n",target);
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)
{
@ -142,63 +166,89 @@ bool fsop_CopyFile (char *source, char *target, progress_callback_t spinner, voi
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;
}
u8 * threadStack = NULL;
lwp_t hthread = LWP_THREAD_NULL;
buff = MEM2_alloc(block*2);
blockIdx = 0;
blockReady = 0;
blockInfo[0] = 0;
blockInfo[1] = 0;
threadStack = MEM2_alloc(STACKSIZE);
LWP_CreateThread (&hthread, thread_CopyFileReader, NULL, threadStack, STACKSIZE, 30);
while (stopThread != 0)
usleep (5);
bytes = 0;
bool spinnerFlag = false;
if (strstr (source, "game.iso")) {
spinner(bytes, size, spinner_data);
spinnerFlag = true;
}
u32 bi;
do
{
rb = fread(buff, 1, block, fs);
wb = fwrite(buff, 1, rb, ft);
while (!blockReady) usleep (1); // Let's wait for incoming block from the thread
bi = blockIdx;
// let's th thread to read the next buff
SET (blockIdx, 1 - blockIdx);
SET (blockReady, 0);
rb = blockInfo[bi];
// write current block
wb = fwrite(&buff[bi*block], 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);
stopThread = 1;
DCFlushRange(&stopThread, sizeof(stopThread));
while (stopThread != -1)
usleep (5);
LWP_JoinThread(hthread, NULL);
MEM2_free(threadStack);
stopThread = 1;
DCFlushRange(&stopThread, sizeof(stopThread));
SAFE_CLOSE(fs);
SAFE_CLOSE(ft);
MEM2_free(buff);
if (err) unlink (target);
if (fsop.breakop || err) return false;
if (err)
{
unlink (target);
return false;
}
return true;
}
@ -211,21 +261,22 @@ static bool doCopyFolder (char *source, char *target, progress_callback_t spinne
struct dirent *pent;
char newSource[300], newTarget[300];
bool ret = true;
// If target folder doesn't exist, create it !
if (!fsop_DirExist(target))
{
gprintf("Creating directory: %s\n",target);
makedir(target);
}
pdir=opendir(source);
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);
@ -236,11 +287,10 @@ static bool doCopyFolder (char *source, char *target, progress_callback_t spinne
}
else // It is a file !
{
strcpy(fsop.op, pent->d_name);
ret = fsop_CopyFile(newSource, newTarget, spinner, spinner_data);
}
}
closedir(pdir);
return ret;
@ -248,10 +298,7 @@ static bool doCopyFolder (char *source, char *target, progress_callback_t spinne
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);
gprintf("DML game USB->SD job started!\n");
return doCopyFolder (source, target, spinner, spinner_data);
return doCopyFolder(source, target, spinner, spinner_data);
}

View File

@ -8,28 +8,6 @@ extern "C"
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);

View File

@ -424,20 +424,24 @@ void CMenu::_game(bool launch)
{
_hideGame();
dir_discHdr *hdr = m_cf.getHdr();
if(currentPartition != SD && m_current_view == COVERFLOW_DML)
{
char gcfolder[MAX_FAT_PATH];
sprintf(gcfolder, "%s [%s]", m_cf.getTitle().toUTF8().c_str(), (char *)hdr->hdr.id);
memset(hdr->path,0,sizeof(hdr->path));
if (DML_GameIsInstalled((char *)hdr->hdr.id, DeviceName[SD]))
{
memset(hdr->path,0,sizeof(hdr->path));
sprintf(hdr->path,"%s",(char*)hdr->hdr.id);
}
else if (DML_GameIsInstalled(gcfolder, DeviceName[SD]))
{
memset(hdr->path,0,sizeof(hdr->path));
sprintf(hdr->path,"%s",gcfolder);
}
else if(!_wbfsOp(CMenu::WO_COPY_GAME))
break;
currentPartition = SD;
}
currentPartition = SD;
m_cf.clear();
_showWaitMessage();

View File

@ -207,37 +207,40 @@ int CMenu::_GCgameInstaller(void *obj)
int CMenu::_GCcopyGame(void *obj)
{
CMenu &m = *(CMenu *)obj;
if(fsop_GetFreeSpaceKb((char*)"sd:/")<fsop_GetFolderKb(m.m_cf.getHdr()->path))
char folder[12];
char source[300];
char target[300];
snprintf(folder, sizeof(folder), DML_DIR, DeviceName[currentPartition]);
snprintf(source, sizeof(source), "%s/%s", folder, m.m_cf.getHdr()->path);
memset(folder, 0, sizeof(folder));
snprintf(folder, sizeof(folder), DML_DIR, DeviceName[SD]);
snprintf(target, sizeof(target), "%s/%s", folder, m.m_cf.getHdr()->path);
int ret;
if(fsop_GetFreeSpaceKb((char*)"sd:/")<fsop_GetFolderKb(source))
{
LWP_MutexLock(m.m_mutex);
m._setThrdMsg(wfmt(m._fmt("wbfsop10", L"Not enough space: %d blocks needed, %d available"), fsop_GetFolderKb(m.m_cf.getHdr()->path), fsop_GetFreeSpaceKb((char*)"sd:/")), 0.f);
m._setThrdMsg(wfmt(m._fmt("wbfsop10", L"Not enough space: %d blocks needed, %d available"), fsop_GetFolderKb(source), fsop_GetFreeSpaceKb((char*)"sd:/")), 0.f);
LWP_MutexUnlock(m.m_mutex);
m.m_thrdWorking = false;
return -1;
ret = -1;
}
else
{
LWP_MutexLock(m.m_mutex);
m._setThrdMsg(L"", 0);
char folder[MAX_FAT_PATH];
snprintf(folder, sizeof(folder), DML_DIR, DeviceName[SD]);
gprintf("Copying from:\n%s\nto:\n%s\n",source,target);
LWP_MutexUnlock(m.m_mutex);
if (!fsop_DirExist(folder))
makedir(folder);
char source[MAX_FAT_PATH];
char target[MAX_FAT_PATH];
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("wbfsop14", L"Game copied, press Back to boot the game."), 1.f);
gprintf("Game copied.\n");
LWP_MutexUnlock(m.m_mutex);
slotLight(true);
ret = 0;
}
m.m_thrdWorking = false;
return 0;
return ret;
}
bool CMenu::_wbfsOp(CMenu::WBFS_OP op)
@ -390,10 +393,10 @@ bool CMenu::_wbfsOp(CMenu::WBFS_OP op)
m_btnMgr.hide(m_wbfsBtnBack);
m_btnMgr.show(m_wbfsLblMessage);
m_btnMgr.setText(m_wbfsLblMessage, L"");
char* gameid = (char *)m_cf.getHdr()->hdr.id;
cfPos = string(gameid);
m_btnMgr.setText(m_wbfsLblDialog, wfmt(_fmt("wbfsop10", L"Copying [%s] %s..."), (u8*)gameid, (u8*)m_cf.getTitle().toUTF8().c_str()));
cfPos = string((char*)m_cf.getHdr()->hdr.id);
m_btnMgr.setText(m_wbfsLblDialog, wfmt(_fmt("wbfsop10", L"Copying [%s] %s..."), (u8*)m_cf.getHdr()->hdr.id, (u8*)m_cf.getTitle().toUTF8().c_str()));
done = true;
upd_dml = true;
m_thrdWorking = true;
m_thrdProgress = 0.f;
m_thrdMessageAdded = false;

File diff suppressed because one or more lines are too long

View File

@ -1 +1 @@
<pd><ViewState><e p="Wiiflow" x="true"></e><e p="Wiiflow\resources" x="false"></e><e p="Wiiflow\source\devicemounter\libwbfs" x="false"></e><e p="Wiiflow\data" x="false"></e><e p="Wiiflow\scripts" x="false"></e><e p="Wiiflow\source" x="true"></e><e p="Wiiflow\source\network" x="false"></e><e p="Wiiflow\source\channel" x="true"></e><e p="Wiiflow\source\menu" x="true"></e><e p="Wiiflow\docs" x="false"></e><e p="Wiiflow\source\cheats" x="true"></e><e p="Wiiflow\portlibs" x="false"></e><e p="Wiiflow\source\config" x="true"></e><e p="Wiiflow\source\devicemounter" x="true"></e><e p="Wiiflow\source\gc" x="false"></e><e p="Wiiflow\source\gecko" x="false"></e><e p="Wiiflow\source\gui" x="true"></e><e p="Wiiflow\source\homebrew" x="true"></e><e p="Wiiflow\source\list" x="true"></e><e p="Wiiflow\source\loader" x="true"></e><e p="Wiiflow\source\memory" x="false"></e><e p="Wiiflow\source\music" x="false"></e><e p="Wiiflow\source\unzip" x="false"></e><e p="Wiiflow\source\wstringEx" x="false"></e><e p="Wiiflow\wii" x="false"></e></ViewState></pd>
<pd><ViewState><e p="Wiiflow" x="true"></e><e p="Wiiflow\resources" x="false"></e><e p="Wiiflow\source\devicemounter\libwbfs" x="false"></e><e p="Wiiflow\data" x="false"></e><e p="Wiiflow\scripts" x="false"></e><e p="Wiiflow\source" x="true"></e><e p="Wiiflow\source\network" x="false"></e><e p="Wiiflow\source\channel" x="true"></e><e p="Wiiflow\source\menu" x="true"></e><e p="Wiiflow\docs" x="false"></e><e p="Wiiflow\source\cheats" x="true"></e><e p="Wiiflow\portlibs" x="false"></e><e p="Wiiflow\source\config" x="true"></e><e p="Wiiflow\source\devicemounter" x="true"></e><e p="Wiiflow\source\gc" x="true"></e><e p="Wiiflow\source\gecko" x="false"></e><e p="Wiiflow\source\gui" x="true"></e><e p="Wiiflow\source\homebrew" x="true"></e><e p="Wiiflow\source\list" x="true"></e><e p="Wiiflow\source\loader" x="true"></e><e p="Wiiflow\source\memory" x="false"></e><e p="Wiiflow\source\music" x="false"></e><e p="Wiiflow\source\unzip" x="false"></e><e p="Wiiflow\source\wstringEx" x="false"></e><e p="Wiiflow\wii" x="false"></e></ViewState></pd>