diff --git a/source/list/list.cpp b/source/list/list.cpp index 3069acf2..ba850c49 100644 --- a/source/list/list.cpp +++ b/source/list/list.cpp @@ -133,20 +133,27 @@ void CList::GetHeaders(safe_vector pathlist, safe_vectorPathToDriveType((*itr).c_str())]; if(strcasecmp(filename, "game.iso") == 0 && strstr((*itr).c_str(), sfmt((strncmp(dml_partition, "sd", 2) != 0) ? DMLgameUSBDir.c_str() : DML_DIR, dml_partition).c_str()) != NULL) - { + { FILE *fp = fopen((*itr).c_str(), "rb"); if( fp ) { - fseek( fp, 0x00, SEEK_SET ); + fseek( fp, 0, SEEK_SET ); fread( tmp.hdr.id, 1, 6, fp ); + u8 gc_disc[1]; + + fread(gc_disc, 1, 1, fp); + GTitle = custom_titles.getString( "TITLES", (const char *) tmp.hdr.id ); int ccolor = custom_titles.getColor( "COVERS", (const char *) tmp.hdr.id, tmp.hdr.casecolor ).intVal(); if( GTitle.size() > 0 || ( gameTDB.IsLoaded() && gameTDB.GetTitle( (char *)tmp.hdr.id, GTitle ) ) ) - { + { mbstowcs( tmp.title, GTitle.c_str(), sizeof(tmp.title) ); Asciify( tmp.title ); + if(gc_disc[0]) + wcslcat(tmp.title, L" disc 2", sizeof(tmp.title)); + tmp.hdr.casecolor = ccolor != 1 ? ccolor : gameTDB.GetCaseColor( (char *)tmp.hdr.id ); if( tmp.hdr.casecolor == 0xffffffff ) tmp.hdr.casecolor = 0; @@ -165,9 +172,12 @@ void CList::GetHeaders(safe_vector pathlist, safe_vector= gc_nbrretry && waitonerror) + { + __WaitForDisc(Disc, 10); + gc_retry = 0; + waitonerror = false; + if(FSTTotal > FSTSize) + message(4, Disc+1, minfo, u_data); + else + message(3, 0, minfo, u_data); + } if(gc_retry >= gc_nbrretry) { if(!skiponerror) @@ -75,6 +85,14 @@ s32 GCDump::__DiscReadRaw(void *outbuf, u32 offset, u32 length) } gc_retry++; } + else if(gc_error == 0x1023a00) + { + __WaitForDisc(Disc, 11); + if(FSTTotal > FSTSize) + message(4, Disc+1, minfo, u_data); + else + message(3, 0, minfo, u_data); + } else { gprintf("Read error(%x) at offset: 0x%08x.\n", gc_error, offset); @@ -92,19 +110,19 @@ s32 GCDump::__DiscReadRaw(void *outbuf, u32 offset, u32 length) return -1; } -s32 GCDump::__DiscWrite(char * path, u32 offset, u32 length, u8 *ReadBuffer, progress_callback_t spinner, void *spinner_data) +s32 GCDump::__DiscWrite(char * path, u32 offset, u32 length, u8 *ReadBuffer) { gprintf("__DiscWrite(%s, 0x%08x, %x)\n", path, offset, length); u32 wrote = 0; FILE *f = fopen(path, "wb"); - wrote = __DiscWriteFile(f, offset, length, ReadBuffer, spinner, spinner_data); + wrote = __DiscWriteFile(f, offset, length, ReadBuffer); SAFE_CLOSE(f); return wrote; } -s32 GCDump::__DiscWriteFile(FILE *f, u32 offset, u32 length, u8 *ReadBuffer, progress_callback_t spinner, void *spinner_data) +s32 GCDump::__DiscWriteFile(FILE *f, u32 offset, u32 length, u8 *ReadBuffer) { u32 toread = 0; u32 wrote = 0; @@ -123,23 +141,26 @@ s32 GCDump::__DiscWriteFile(FILE *f, u32 offset, u32 length, u8 *ReadBuffer, pro length -= toread; gc_done += toread; if(spinner) - spinner(gc_done/1024, DiscSizeCalculated, spinner_data); + spinner(gc_done/1024, DiscSizeCalculated, u_data); } return wrote; } -bool GCDump::__WaitForDisc(u8 dsc, char *minfo, u32 msg, message_callback_t message, void *message_data) +bool GCDump::__WaitForDisc(u8 dsc, u32 msg) { u8 *ReadBuffer = (u8 *)MEM2_alloc(0x440); u32 cover = 0; - bool done = false; - *(u32*)0xCD0000C0 |= 0x20; + bool done = false; while(!done) - { - message( msg, dsc+1, minfo, message_data); + { + message( msg, dsc+1, minfo, u_data); while(1) { + *(u32*)0xCD0000C0 |= 0x20; + usleep( 1000000 ); + *(u32*)0xCD0000C0 &= ~0x20; + usleep( 1000000 ); WDVD_GetCoverStatus(&cover); if(!(cover & 0x2)) break; @@ -147,6 +168,10 @@ bool GCDump::__WaitForDisc(u8 dsc, char *minfo, u32 msg, message_callback_t mess while(1) { + *(u32*)0xCD0000C0 |= 0x20; + usleep( 1000000 ); + *(u32*)0xCD0000C0 &= ~0x20; + usleep( 1000000 ); if(Disc_Wait() < 0) continue; @@ -169,33 +194,32 @@ bool GCDump::__WaitForDisc(u8 dsc, char *minfo, u32 msg, message_callback_t mess Disc2 = *(vu8*)(ReadBuffer+0x06); if(ID == ID2 && Disc2 == dsc) - { - *(u32*)0xCD0000C0 &= ~0x20; + { done = true; break; } else if(ID == ID2 && Disc2 != dsc) { - message( 7, dsc+1, NULL, message_data); + message( 7, Disc2+1, NULL, u_data); usleep( 5000000 ); break; } else if(ID != ID2) { - message( 8, 0, NULL, message_data); + message( 8, 0, NULL, u_data); usleep( 5000000 ); break; } } else if(Disc_IsWii() == 0) { - message( 5, 0, NULL, message_data); + message( 5, 0, NULL, u_data); usleep( 5000000 ); break; } else { - message( 6, 0, NULL, message_data); + message( 6, 0, NULL, u_data); usleep( 5000000 ); break; @@ -206,7 +230,7 @@ bool GCDump::__WaitForDisc(u8 dsc, char *minfo, u32 msg, message_callback_t mess return done; } -s32 GCDump::DumpGame(progress_callback_t spinner, message_callback_t message, void *spinner_data) +s32 GCDump::DumpGame() { static gc_discHdr gcheader ATTRIBUTE_ALIGN(32); @@ -220,8 +244,7 @@ s32 GCDump::DumpGame(progress_callback_t spinner, message_callback_t message, vo char folder[MAX_FAT_PATH]; bzero(folder, MAX_FAT_PATH); char gamepath[MAX_FAT_PATH]; - bzero(gamepath, MAX_FAT_PATH); - char minfo[74]; + bzero(gamepath, MAX_FAT_PATH); for( j=0; j<2; ++j) { @@ -253,6 +276,7 @@ s32 GCDump::DumpGame(progress_callback_t spinner, message_callback_t message, vo } ID = *(vu32*)(ReadBuffer); + Disc = *(vu8*)(ReadBuffer+0x06); ApploaderSize = *(vu32*)(ReadBuffer+0x400); DOLOffset = *(vu32*)(ReadBuffer+0x420); FSTOffset = *(vu32*)(ReadBuffer+0x424); @@ -285,9 +309,9 @@ s32 GCDump::DumpGame(progress_callback_t spinner, message_callback_t message, vo snprintf(minfo, sizeof(minfo), "[%.06s] %s", (char *)gcheader.id, gcheader.title); if(FSTTotal > FSTSize) - message(4, j+1, minfo, spinner_data); + message(4, j+1, minfo, u_data); else - message(3, 0, minfo, spinner_data); + message(3, 0, minfo, u_data); gprintf("Dumping: %s %s\n", gcheader.title, compressed ? "compressed" : "full"); @@ -312,15 +336,15 @@ s32 GCDump::DumpGame(progress_callback_t spinner, message_callback_t message, vo gprintf("Writing %s/boot.bin\n", folder); snprintf(gamepath, sizeof(gamepath), "%s/boot.bin", folder); - gc_done += __DiscWrite(gamepath, 0, 0x440, ReadBuffer, spinner, spinner_data); + gc_done += __DiscWrite(gamepath, 0, 0x440, ReadBuffer); gprintf("Writing %s/bi2.bin\n", folder); snprintf(gamepath, sizeof(gamepath), "%s/bi2.bin", folder); - gc_done += __DiscWrite(gamepath, 0x440, 0x2000, ReadBuffer, spinner, spinner_data); + gc_done += __DiscWrite(gamepath, 0x440, 0x2000, ReadBuffer); gprintf("Writing %s/apploader.img\n", folder); snprintf(gamepath, sizeof(gamepath), "%s/apploader.img", folder); - gc_done += __DiscWrite(gamepath, 0x2440, ApploaderSize, ReadBuffer, spinner, spinner_data); + gc_done += __DiscWrite(gamepath, 0x2440, ApploaderSize, ReadBuffer); } snprintf(gamepath, sizeof(gamepath), "%s/%s [%.06s]%s/game.iso", sfmt((strncmp(gamepartition, "sd", 2) != 0) ? usb_dml_game_dir : DML_DIR, gamepartition).c_str(), gcheader.title, (char *)gcheader.id, j ? "2" : ""); @@ -335,7 +359,7 @@ s32 GCDump::DumpGame(progress_callback_t spinner, message_callback_t message, vo FILE *f; f = fopen(gamepath, "wb"); - ret = __DiscWriteFile(f, 0, (FSTOffset + FSTSize), ReadBuffer, spinner, spinner_data); + ret = __DiscWriteFile(f, 0, (FSTOffset + FSTSize), ReadBuffer); wrote += (FSTOffset + FSTSize); gc_done += wrote; @@ -369,7 +393,7 @@ s32 GCDump::DumpGame(progress_callback_t spinner, message_callback_t message, vo break; } } - ret = __DiscWriteFile(f, fst[i].FileOffset, fst[i].FileLength, ReadBuffer, spinner, spinner_data); + ret = __DiscWriteFile(f, fst[i].FileOffset, fst[i].FileLength, ReadBuffer); gprintf("Writing: %d/%d: %s from 0x%08x to 0x%08x(%i)\n", i, FSTEnt, FSTNameOff + fst[i].NameOffset, fst[i].FileOffset, wrote, align); if( ret >= 0 ) { @@ -395,7 +419,7 @@ s32 GCDump::DumpGame(progress_callback_t spinner, message_callback_t message, vo } else { - ret = __DiscWrite(gamepath, 0, DiscSize, ReadBuffer, spinner, spinner_data); + ret = __DiscWrite(gamepath, 0, DiscSize, ReadBuffer); if( ret < 0 ) { MEM2_free(ReadBuffer); @@ -408,7 +432,7 @@ s32 GCDump::DumpGame(progress_callback_t spinner, message_callback_t message, vo MEM2_free(FSTBuffer); if(FSTTotal > FSTSize && !j) - __WaitForDisc(1, minfo, 9, message, spinner_data); + __WaitForDisc(1, 9); else break; } @@ -418,7 +442,7 @@ s32 GCDump::DumpGame(progress_callback_t spinner, message_callback_t message, vo return gc_skipped; } -s32 GCDump::CheckSpace(u32 *needed, bool comp, message_callback_t message, void *message_data) +s32 GCDump::CheckSpace(u32 *needed, bool comp) { static gc_discHdr gcheader ATTRIBUTE_ALIGN(32); @@ -426,8 +450,6 @@ s32 GCDump::CheckSpace(u32 *needed, bool comp, message_callback_t message, void u32 size = 0; u32 j; - char minfo[74]; - for( j=0; j<2; ++j) { s32 ret = __DiscReadRaw(ReadBuffer, 0, 0x440); @@ -454,7 +476,7 @@ s32 GCDump::CheckSpace(u32 *needed, bool comp, message_callback_t message, void snprintf(minfo, sizeof(minfo), "[%.06s] %s", (char *)gcheader.id, gcheader.title); - message( 2, 0, minfo, message_data); + message( 2, 0, minfo, u_data); if(writeexfiles) { @@ -499,7 +521,7 @@ s32 GCDump::CheckSpace(u32 *needed, bool comp, message_callback_t message, void { if((fst[i].FileOffset & (align-1)) == 0 || force_32k_align) { - correction = 0x00; + correction = 0; while(((size+correction) & (align-1)) != 0) correction++; size += correction; @@ -515,14 +537,14 @@ s32 GCDump::CheckSpace(u32 *needed, bool comp, message_callback_t message, void if(FSTTotal > FSTSize) { if(Disc == 0 && j == 0) - __WaitForDisc(1, minfo, 1, message, message_data); + __WaitForDisc(1, 1); else if(Disc == 0x01 && j == 0) - __WaitForDisc(0, minfo, 1, message, message_data); + __WaitForDisc(0, 1); if(j == 1) { if(Disc == 0x01) - __WaitForDisc(0, minfo, 1, message, message_data); + __WaitForDisc(0, 1); break; } @@ -531,9 +553,31 @@ s32 GCDump::CheckSpace(u32 *needed, bool comp, message_callback_t message, void break; } MEM2_free(ReadBuffer); - DiscSizeCalculated = (size/1024); - *needed = size/0x8000; - gprintf("Free space needed: %d Mb (%x blocks)\n", (size/1024)/1024, size/0x8000); + DiscSizeCalculated = size/0x400; + *needed = (size/0x8000) >> 2; + gprintf("Free space needed: %d Mb (%d blocks)\n", size/0x100000, (size/0x8000) >> 2); + return 0; +} + +u32 GCDump::GetFreeSpace(char *path, u32 Value) +{ + struct statvfs stats; + memset(&stats, 0, sizeof(stats)); + statvfs(path , &stats); + + u64 free = (u64)stats.f_frsize * (u64)stats.f_bfree; + + switch(Value) + { + case KB: + return free/0x400; + case BL: + return (free/0x8000) >> 2; + case MB: + return free/0x100000; + case GB: + return free/0x40000000; + } return 0; } diff --git a/source/loader/gc_disc.hpp b/source/loader/gc_disc.hpp index e07c1577..2756b79a 100644 --- a/source/loader/gc_disc.hpp +++ b/source/loader/gc_disc.hpp @@ -31,10 +31,18 @@ typedef void (*progress_callback_t)(int status,int total,void *user_data); typedef void (*message_callback_t)(int message, int info, char *cinfo, void *user_data); +enum spcall +{ + KB = 0, + BL, + MB, + GB, +}; + class GCDump { public: - void Init(bool skip, bool comp, bool wexf, bool align, u32 nretry, u32 rsize, const char* partition, const char* m_DMLgameDir) + void Init(bool skip, bool comp, bool wexf, bool align, u32 nretry, u32 rsize, const char* partition, const char* m_DMLgameDir, progress_callback_t i_spinner, message_callback_t i_message, void *i_udata) { skiponerror = skip; compressed = comp; @@ -45,16 +53,26 @@ public: gamepartition = partition; usb_dml_game_dir = m_DMLgameDir; gc_skipped = 0; + spinner = i_spinner; + message = i_message; + u_data = i_udata; + waitonerror = true; } - s32 DumpGame(progress_callback_t spinner, message_callback_t message, void *spinner_data); - s32 CheckSpace(u32 *needed, bool comp, message_callback_t message, void *message_data); + s32 DumpGame( ); + s32 CheckSpace(u32 *needed, bool comp); + u32 GetFreeSpace(char *path, u32 Value); private: + progress_callback_t spinner; + message_callback_t message; + void *u_data; bool force_32k_align; bool skiponerror; bool compressed; bool writeexfiles; - const char* gamepartition; - const char* usb_dml_game_dir; + bool waitonerror; + const char *gamepartition; + const char *usb_dml_game_dir; + char minfo[74]; u8 Disc; u8 Disc2; u32 gc_nbrretry; @@ -103,8 +121,8 @@ private: }; } FST; s32 __DiscReadRaw(void *outbuf, u32 offset, u32 length); - s32 __DiscWrite(char * path, u32 offset, u32 length, u8 *ReadBuffer, progress_callback_t spinner, void *spinner_data); - s32 __DiscWriteFile(FILE *f, u32 offset, u32 length, u8 *ReadBuffer, progress_callback_t spinner, void *spinner_data); - bool __WaitForDisc(u8 dsc, char *minfo, u32 msg, message_callback_t message, void *message_data); + s32 __DiscWrite(char * path, u32 offset, u32 length, u8 *ReadBuffer); + s32 __DiscWriteFile(FILE *f, u32 offset, u32 length, u8 *ReadBuffer); + bool __WaitForDisc(u8 dsc, u32 msg); }; #endif \ No newline at end of file diff --git a/source/menu/menu_wbfs.cpp b/source/menu/menu_wbfs.cpp index 064c5bdc..c48a0dc2 100644 --- a/source/menu/menu_wbfs.cpp +++ b/source/menu/menu_wbfs.cpp @@ -94,6 +94,10 @@ void CMenu::_Messenger(int message, int info, char *cinfo, void *user_data) m._setThrdMsg(m._t("wbfsop21", L"This is a disc of another game!!"), m.m_progress); if(message == 9) m._setThrdMsg(wfmt(m._fmt("wbfsop22", L"Installing %s...\n Please insert disc 2 to continue"), cinfo), m.m_progress); + if(message == 10) + m._setThrdMsg(m._t("wbfsop25", L"Disc read error!! Please clean the disc"), m.m_progress); + if(message == 11) + m._setThrdMsg(m._t("wbfsop26", L"Disc ejected!! Please insert disc again"), m.m_progress); LWP_MutexUnlock(m.m_mutex); } @@ -113,7 +117,7 @@ int CMenu::_gameInstaller(void *obj) WBFS_DiskSpace(&used, &free); WBFS_DVD_Size(&comp_size, &real_size); - if ((f32)comp_size + (f32)128*1024 >= free * GB_SIZE) + if((f32)comp_size + (f32)128*1024 >= free * GB_SIZE) { LWP_MutexLock(m.m_mutex); m._setThrdMsg(wfmt(m._fmt("wbfsop10", L"Not enough space: %lld blocks needed, %i available"), comp_size, free), 0.f); @@ -154,7 +158,7 @@ int CMenu::_GCgameInstaller(void *obj) if(skip) rsize = 8192; // Use small chunks when skip on error is enabled - m_gcdump.Init(skip, comp, wexf, alig, nretry, rsize,DeviceName[currentPartition],m.m_DMLgameDir.c_str()); + m_gcdump.Init(skip, comp, wexf, alig, nretry, rsize,DeviceName[currentPartition],m.m_DMLgameDir.c_str(), CMenu::_addDiscProgress, CMenu::_Messenger, obj); int ret; m.m_progress = 0.f; @@ -170,7 +174,7 @@ int CMenu::_GCgameInstaller(void *obj) u32 needed = 0; - ret = m_gcdump.CheckSpace(&needed, comp, CMenu::_Messenger, obj); + ret = m_gcdump.CheckSpace(&needed, comp); if(ret != 0) { m._setThrdMsg(m._t("wbfsop9", L"An error has occurred"), 1.f); @@ -178,20 +182,22 @@ int CMenu::_GCgameInstaller(void *obj) return ret; } - if (fsop_GetFreeSpaceKb(partition) <= needed) + if(m_gcdump.GetFreeSpace(partition, BL) <= needed) { + gprintf("Free space available: %d Mb (%d blocks)\n", m_gcdump.GetFreeSpace(partition, MB), m_gcdump.GetFreeSpace(partition, BL)); LWP_MutexLock(m.m_mutex); - m._setThrdMsg(wfmt(m._fmt("wbfsop10", L"Not enough space: %d blocks needed, %d available"), needed, fsop_GetFreeSpaceKb(partition)), 0.f); + m._setThrdMsg(wfmt(m._fmt("wbfsop24", L"Not enough space: %d blocks needed, %d available"), needed, m_gcdump.GetFreeSpace(partition, BL)), 0.f); LWP_MutexUnlock(m.m_mutex); ret = -1; } else { + gprintf("Free space available: %d Mb (%d blocks)\n", m_gcdump.GetFreeSpace(partition, MB), m_gcdump.GetFreeSpace(partition, BL)); LWP_MutexLock(m.m_mutex); m._setThrdMsg(L"", 0); LWP_MutexUnlock(m.m_mutex); - ret = m_gcdump.DumpGame(CMenu::_addDiscProgress, CMenu::_Messenger, obj); + ret = m_gcdump.DumpGame(); LWP_MutexLock(m.m_mutex); if(ret == 0) m._setThrdMsg(m._t("wbfsop8", L"Game installed"), 1.f); diff --git a/wii/wiiflow/Languages/dutch.ini b/wii/wiiflow/Languages/dutch.ini index f69064fa..f8fbce03 100644 --- a/wii/wiiflow/Languages/dutch.ini +++ b/wii/wiiflow/Languages/dutch.ini @@ -210,7 +210,7 @@ wbfsadddlg=Plaats het te kopiëren spel in de disc sleuf, klik daarna op Start. wbfsop1=Installeer Spel wbfsop10=Niet genoeg ruimte: %i blokken benodigd, %i beschikbaar wbfsop11=Kopieër Spel -wbfsop12=DVD Lees Fout(%d) +wbfsop12=DVD lees fout(%d) wbfsop13=Spel geïnstalleerd, maar bevat %d leesfouten wbfsop14=Spel gekopieërd, klik op terug om spel te starten wbfsop15=Benodigde ruimte aan het berekenen voor %s @@ -223,6 +223,9 @@ wbfsop20=Je hebt disc %d terug in de disc sleuf gedaan! wbfsop21=Dit is een disc van een ander spel! wbfsop22=Bezig met installeren van %s...\nDoe disc 2 in de disc sleuf om door the gaan wbfsop23=Benodigde ruimte aan het berekenen voor %s...\nDoe disc %d in de disc sleuf om door the gaan +wbfsop24=Niet genoeg ruimte:: %d blokken benodigd, %d beschikbaar +wbfsop25=DVD lees fout!! Maak de disc schoon A.U.B. +wbfsop26=Disc verwijderd!! Doe de disc terug in de disc sleuf A.U.B. wbfsop4=Terug wbfsop5=Start wbfsop6=Bezig met installeren van [%s] %s... diff --git a/wii/wiiflow/Languages/english.ini b/wii/wiiflow/Languages/english.ini index 402f5f64..303966d1 100644 --- a/wii/wiiflow/Languages/english.ini +++ b/wii/wiiflow/Languages/english.ini @@ -218,8 +218,19 @@ wbfsop11=Copy Game wbfsop12=DVDError(%d) wbfsop13=Game installed, but disc contains errors (%d) wbfsop14=Game copied, press Back to boot the game. -wbfsop15=Copying [%s] %s... +wbfsop15=Calculating space needed for %s +wbfsop16=Installing %s +wbfsop17=Installing %s disc %d/2 +wbfsop18=This is a Wii disc! +wbfsop19=This is not a Gamecube disc! wbfsop2=Delete Game +wbfsop20=You inserted disc %d again!! +wbfsop21=This is a disc of another game!! +wbfsop22=Installing %s...\n Please insert disc 2 to continue +wbfsop23=Calculating space needed for %s...\n Please insert disc %d to continue +wbfsop24=Not enough space: %d blocks needed, %d available +wbfsop25=Disc read error!! Please clean the disc +wbfsop26=Disc ejected!! Please insert disc again wbfsop4=Back wbfsop5=Go wbfsop6=Installing [%s] %s...