From fcf9d344f789c86dae9bcca4a44879b754da74d8 Mon Sep 17 00:00:00 2001 From: "fix94.1" Date: Sat, 3 Mar 2012 17:16:11 +0000 Subject: [PATCH] -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 --- source/gc/fileOps.c | 169 ++++++++++++++++++++++++-------------- source/gc/fileOps.h | 22 ----- source/menu/menu_game.cpp | 10 ++- source/menu/menu_wbfs.cpp | 35 ++++---- wiiflow.pnproj | 2 +- wiiflow.pnps | 2 +- 6 files changed, 136 insertions(+), 104 deletions(-) diff --git a/source/gc/fileOps.c b/source/gc/fileOps.c index ba9dd52a..caee318d 100644 --- a/source/gc/fileOps.c +++ b/source/gc/fileOps.c @@ -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); } diff --git a/source/gc/fileOps.h b/source/gc/fileOps.h index bf9f7d19..a48d7808 100644 --- a/source/gc/fileOps.h +++ b/source/gc/fileOps.h @@ -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); diff --git a/source/menu/menu_game.cpp b/source/menu/menu_game.cpp index 46d130cc..e59b029c 100644 --- a/source/menu/menu_game.cpp +++ b/source/menu/menu_game.cpp @@ -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(); diff --git a/source/menu/menu_wbfs.cpp b/source/menu/menu_wbfs.cpp index 472af8dd..9602e38f 100644 --- a/source/menu/menu_wbfs.cpp +++ b/source/menu/menu_wbfs.cpp @@ -207,37 +207,40 @@ int CMenu::_GCgameInstaller(void *obj) int CMenu::_GCcopyGame(void *obj) { CMenu &m = *(CMenu *)obj; - if(fsop_GetFreeSpaceKb((char*)"sd:/")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:/")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; diff --git a/wiiflow.pnproj b/wiiflow.pnproj index ed0e981f..d24fc023 100644 --- a/wiiflow.pnproj +++ b/wiiflow.pnproj @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/wiiflow.pnps b/wiiflow.pnps index 0eaf061c..4734953c 100644 --- a/wiiflow.pnps +++ b/wiiflow.pnps @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file