Again some dumper changes:

* It's now possible to dump games that come with 2 discs
* Added messenger callback to interact with the thread message

Todo:

* Cleanup the code
This commit is contained in:
overjoy.psm 2012-02-29 00:19:50 +00:00
parent fa1852bfa9
commit c8ca36600d
4 changed files with 565 additions and 200 deletions

View File

@ -26,6 +26,7 @@
***************************************************************************/
#include <stdio.h>
#include <unistd.h>
#include <ogcsys.h>
#include <sys/statvfs.h>
@ -138,28 +139,27 @@ s32 GCDump::__DiscWriteAligned(FILE *f, u32 offset, u32 length, u8 *ReadBuffer)
return wrote;
}
s32 GCDump::DumpGame(progress_callback_t spinner, void *spinner_data)
s32 GCDump::DumpGame(progress_callback_t spinner, message_callback_t message, void *spinner_data)
{
static gc_discHdr gcheader ATTRIBUTE_ALIGN(32);
u8 *ReadBuffer = (u8 *)MEM2_alloc(0x40);
u8 *FSTBuffer;
u32 wrote = 0;
u8 *ReadBuffer = (u8 *)MEM2_alloc(gc_readsize);
u32 j;
u32 ApploaderSize = 0;
u32 DOLOffset = 0;
u32 DOLSize = 0;
u32 FSTOffset = 0;
u32 FSTSize = 0;
u32 FSTEnt = 0;
u32 GamePartOffset = 0;
u32 DataSize = 0;
char *FSTNameOff = (char *)NULL;
char folder[MAX_FAT_PATH];
bzero(folder, MAX_FAT_PATH);
char gamepath[MAX_FAT_PATH];
bzero(gamepath, MAX_FAT_PATH);
char minfo[74];
for( j=0; j<2; ++j)
{
bool done = false;
u8 *FSTBuffer;
u32 wrote = 0;
s32 ret = Disc_ReadGCHeader(&gcheader);
Asciify2(gcheader.title);
@ -167,23 +167,25 @@ s32 GCDump::DumpGame(progress_callback_t spinner, void *spinner_data)
snprintf(folder, sizeof(folder), "%s:/games/", gamepartition);
if(!fsop_DirExist(folder))
fsop_MakeFolder(folder);
snprintf(folder, sizeof(folder), "%s:/games/%s [%s]", gamepartition, gcheader.title, (char *)gcheader.id);
snprintf(folder, sizeof(folder), "%s:/games/%s [%.06s]%s", gamepartition, gcheader.title, (char *)gcheader.id, j ? "2" : "");
if(!fsop_DirExist(folder))
fsop_MakeFolder(folder);
ret = __DiscReadRaw(ReadBuffer, 0x400, 0x40);
ret = __DiscReadRaw(ReadBuffer, 0, 0x440);
if(ret > 0)
{
MEM2_free(ReadBuffer);
return 0x31100;
}
ApploaderSize = *(vu32*)(ReadBuffer);
DOLOffset = *(vu32*)(ReadBuffer+0x20);
FSTOffset = *(vu32*)(ReadBuffer+0x24);
FSTSize = *(vu32*)(ReadBuffer+0x28);
GamePartOffset = *(vu32*)(ReadBuffer+0x34);
DataSize = *(vu32*)(ReadBuffer+0x38);
ID = *(vu32*)(ReadBuffer);
ApploaderSize = *(vu32*)(ReadBuffer+0x400);
DOLOffset = *(vu32*)(ReadBuffer+0x420);
FSTOffset = *(vu32*)(ReadBuffer+0x424);
FSTSize = *(vu32*)(ReadBuffer+0x428);
FSTTotal = *(vu32*)(ReadBuffer+0x42c);
GamePartOffset = *(vu32*)(ReadBuffer+0x434);
DataSize = *(vu32*)(ReadBuffer+0x438);
DOLSize = FSTOffset - DOLOffset;
DiscSize = DataSize + GamePartOffset;
@ -200,15 +202,19 @@ s32 GCDump::DumpGame(progress_callback_t spinner, void *spinner_data)
}
FSTable = (u8*)FSTBuffer;
MEM2_free(ReadBuffer);
ReadBuffer = (u8 *)MEM2_alloc(gc_readsize);
FSTEnt = *(u32*)(FSTable+0x08);
FSTNameOff = (char*)(FSTable + FSTEnt * 0x0C);
FST *fst = (FST *)(FSTable);
snprintf(minfo, sizeof(minfo), "[%.06s] %s", (char *)gcheader.id, gcheader.title);
if(FSTTotal > FSTSize)
message( 4, j+1, minfo, spinner_data);
else
message( 3, 0, minfo, spinner_data);
gprintf("Dumping: %s %s\n", gcheader.title, compressed ? "compressed" : "full");
gprintf("Apploader size : %d\n", ApploaderSize);
@ -222,7 +228,7 @@ s32 GCDump::DumpGame(progress_callback_t spinner, void *spinner_data)
if(writeexfiles)
{
snprintf(folder, sizeof(folder), "%s:/games/%s [%s]/sys", gamepartition, gcheader.title, (char *)gcheader.id);
snprintf(folder, sizeof(folder), "%s:/games/%s [%.06s]%s/sys", gamepartition, gcheader.title, (char *)gcheader.id, j ? "2" : "");
if(!fsop_DirExist(folder))
fsop_MakeFolder(folder);
@ -239,7 +245,7 @@ s32 GCDump::DumpGame(progress_callback_t spinner, void *spinner_data)
__DiscWrite(gamepath, 0x2440, ApploaderSize, ReadBuffer, spinner, spinner_data);
}
snprintf(gamepath, sizeof(gamepath), "%s:/games/%s [%s]/game.iso", gamepartition, gcheader.title, (char *)gcheader.id);
snprintf(gamepath, sizeof(gamepath), "%s:/games/%s [%.06s]%s/game.iso", gamepartition, gcheader.title, (char *)gcheader.id, j ? "2" : "");
gprintf("Writing %s\n", gamepath);
if(compressed)
@ -287,6 +293,7 @@ s32 GCDump::DumpGame(progress_callback_t spinner, void *spinner_data)
{
spinner(FSTEnt, FSTEnt, spinner_data);
MEM2_free(ReadBuffer);
MEM2_free(FSTBuffer);
SAFE_CLOSE(f);
return gc_error;
}
@ -306,36 +313,130 @@ s32 GCDump::DumpGame(progress_callback_t spinner, void *spinner_data)
if( ret < 0 )
{
MEM2_free(ReadBuffer);
MEM2_free(FSTBuffer);
return gc_error;
}
gprintf("Done!! Disc size: %d\n", DiscSize);
}
MEM2_free(ReadBuffer);
MEM2_free(FSTBuffer);
if(FSTTotal > FSTSize && !j)
{
*(u32*)0xCD0000C0 |= 0x20;
u32 cover = 0;
message( 9, 0, minfo, spinner_data);
while(!done)
{
while(1)
{
WDVD_GetCoverStatus(&cover);
if(!(cover & 0x2))
break;
}
while(1)
{
if(Disc_Wait() < 0)
continue;
if(Disc_Open() < 0)
return 1;
if(Disc_IsGC() == 0)
{
s32 ret = __DiscReadRaw(ReadBuffer, 0, 0x440);
if(ret > 0)
return 1;
ID2 = *(vu32*)(ReadBuffer);
Disc = *(vu8*)(ReadBuffer+0x06);
if(ID == ID2 && Disc == 0x01)
{
done = true;
*(u32*)0xCD0000C0 &= ~0x20;
break;
}
else if(ID == ID2 && Disc == 0x00)
{
message( 7, 1, NULL, spinner_data);
usleep( 5000000 );
break;
}
else if(ID != ID2)
{
message( 8, 0, NULL, spinner_data);
usleep( 5000000 );
break;
}
}
else if(Disc_IsWii() == 0)
{
message( 5, 0, NULL, spinner_data);
usleep( 5000000 );
break;
}
else
{
message( 6, 0, NULL, spinner_data);
usleep( 5000000 );
break;
}
}
}
}
else
{
break;
}
}
MEM2_free(ReadBuffer);
return gc_skipped;
}
s32 GCDump::CheckSpace(u32 *needed, bool comp)
s32 GCDump::CheckSpace(u32 *needed, bool comp, message_callback_t message, void *message_data)
{
u8 *ReadBuffer = (u8 *)MEM2_alloc(0x40);
s32 ret = __DiscReadRaw(ReadBuffer, 0x400, 0x40);
if(ret > 0)
return 1;
u32 ApploaderSize = *(vu32*)(ReadBuffer);
u32 FSTOffset = *(vu32*)(ReadBuffer+0x24);
u32 FSTSize = *(vu32*)(ReadBuffer+0x28);
u32 GamePartOffset = *(vu32*)(ReadBuffer+0x34);
u32 DataSize = *(vu32*)(ReadBuffer+0x38);
u32 DiscSize = DataSize + GamePartOffset;
MEM2_free(ReadBuffer);
static gc_discHdr gcheader ATTRIBUTE_ALIGN(32);
u8 *ReadBuffer = (u8 *)MEM2_alloc(0x440);
u32 size = 0;
u32 j;
char minfo[74];
for( j=0; j<2; ++j)
{
s32 ret = __DiscReadRaw(ReadBuffer, 0, 0x440);
if(ret > 0)
{
MEM2_free(ReadBuffer);
return 1;
}
ID = *(vu32*)(ReadBuffer);
ID2 = 0;
Disc = *(vu8*)(ReadBuffer+0x06);
Disc2 = 0;
ApploaderSize = *(vu32*)(ReadBuffer+0x400);
FSTOffset = *(vu32*)(ReadBuffer+0x424);
FSTSize = *(vu32*)(ReadBuffer+0x428);
FSTTotal = *(vu32*)(ReadBuffer+0x42c);
GamePartOffset = *(vu32*)(ReadBuffer+0x434);
DataSize = *(vu32*)(ReadBuffer+0x438);
DiscSize = DataSize + GamePartOffset;
bool done = false;
Disc_ReadGCHeader(&gcheader);
Asciify2(gcheader.title);
snprintf(minfo, sizeof(minfo), "[%.06s] %s", (char *)gcheader.id, gcheader.title);
message( 2, 0, minfo, message_data);
if(writeexfiles)
{
@ -377,7 +478,225 @@ s32 GCDump::CheckSpace(u32 *needed, bool comp)
}
MEM2_free(FSTBuffer);
}
if(FSTTotal > FSTSize)
{
u32 cover = 0;
if(Disc == 0x00 && j == 0)
{
while(!done)
{
message( 1, 2, minfo, message_data);
while(1)
{
WDVD_GetCoverStatus(&cover);
if(!(cover & 0x2))
break;
}
while(1)
{
if(Disc_Wait() < 0)
continue;
if(Disc_Open() < 0)
{
MEM2_free(ReadBuffer);
return 1;
}
if(Disc_IsGC() == 0)
{
s32 ret = __DiscReadRaw(ReadBuffer, 0, 0x440);
if(ret > 0)
{
MEM2_free(ReadBuffer);
return 1;
}
ID2 = *(vu32*)(ReadBuffer);
Disc2 = *(vu8*)(ReadBuffer+0x06);
if(ID == ID2 && Disc2 == 0x01)
{
done = true;
break;
}
else if(ID == ID2 && Disc2 == 0x00)
{
message( 7, 1, NULL, message_data);
usleep( 5000000 );
break;
}
else if(ID != ID2)
{
message( 8, 0, NULL, message_data);
usleep( 5000000 );
break;
}
}
else if(Disc_IsWii() == 0)
{
message( 5, 0, NULL, message_data);
usleep( 5000000 );
break;
}
else
{
message( 6, 0, NULL, message_data);
usleep( 5000000 );
break;
}
}
}
}
else if(Disc == 0x01 && j == 0)
{
while(!done)
{
message( 1, 1, minfo, message_data);
while(1)
{
WDVD_GetCoverStatus(&cover);
if(!(cover & 0x2))
break;
}
while(1)
{
if(Disc_Wait() < 0)
continue;
if(Disc_Open() < 0)
{
MEM2_free(ReadBuffer);
return 1;
}
if(Disc_IsGC() == 0)
{
s32 ret = __DiscReadRaw(ReadBuffer, 0, 0x440);
if(ret > 0)
{
MEM2_free(ReadBuffer);
return 1;
}
ID2 = *(vu32*)(ReadBuffer);
Disc2 = *(vu8*)(ReadBuffer+0x06);
if(ID == ID2 && Disc2 == 0x00)
{
done = true;
break;
}
else if(ID == ID2 && Disc2 == 0x01)
{
message( 7, 2, NULL, message_data);
usleep( 5000000 );
break;
}
else if(ID != ID2)
{
message( 8, 0, NULL, message_data);
usleep( 5000000 );
break;
}
}
else if(Disc_IsWii() == 0)
{
message( 5, 0, NULL, message_data);
usleep( 5000000 );
break;
}
else
{
message( 6, 0, NULL, message_data);
usleep( 5000000 );
break;
}
}
}
}
if(j == 1)
{
if(Disc == 0x01)
{
while(!done)
{
message( 1, 1, minfo, message_data);
while(1)
{
WDVD_GetCoverStatus(&cover);
if(!(cover & 0x2))
break;
}
while(1)
{
if(Disc_Wait() < 0)
continue;
if(Disc_Open() < 0)
{
MEM2_free(ReadBuffer);
return 1;
}
if(Disc_IsGC() == 0)
{
s32 ret = __DiscReadRaw(ReadBuffer, 0, 0x440);
if(ret > 0)
{
MEM2_free(ReadBuffer);
return 1;
}
ID2 = *(vu32*)(ReadBuffer);
Disc2 = *(vu8*)(ReadBuffer+0x06);
if(ID == ID2 && Disc2 == 0x00)
{
done = true;
break;
}
else if(ID == ID2 && Disc2 == 0x01)
{
message( 7, 2, NULL, message_data);
usleep( 5000000 );
break;
}
else if(ID != ID2)
{
message( 8, 0, NULL, message_data);
usleep( 5000000 );
break;
}
}
else if(Disc_IsWii() == 0)
{
message( 5, 0, NULL, message_data);
usleep( 5000000 );
break;
}
else
{
message( 6, 0, NULL, message_data);
usleep( 5000000 );
break;
}
}
}
}
break;
}
}
else
break;
}
MEM2_free(ReadBuffer);
*needed = size/0x8000;
gprintf("Free space needed: %d bytes (%x blocks)\n", size, size/0x8000);
gprintf("Free space needed: %d Mb (%x blocks)\n", (size/1024)/1024, size/0x8000);
return 0;
}

View File

@ -29,6 +29,7 @@
#define GC_DISC_H_
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);
class GCDump
{
@ -44,19 +45,32 @@ public:
gamepartition = partition;
gc_skipped = 0;
}
s32 DumpGame(progress_callback_t spinner, void *spinner_data);
s32 CheckSpace(u32 *needed, bool comp);
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);
private:
bool force_32k_align;
bool skiponerror;
bool compressed;
bool writeexfiles;
const char* gamepartition;
u8 Disc;
u8 Disc2;
u32 gc_nbrretry;
u32 gc_error;
u32 gc_retry;
u32 gc_skipped;
u32 gc_readsize;
u32 ID;
u32 ID2;
u32 ApploaderSize;
u32 DOLOffset;
u32 DOLSize;
u32 FSTOffset;
u32 FSTSize;
u32 FSTTotal;
u32 FSTEnt;
u32 GamePartOffset;
u32 DataSize;
u32 DiscSize;
typedef struct
{

View File

@ -929,6 +929,7 @@ private:
void LoadView(void);
void _getGrabStatus(void);
static void _addDiscProgress(int status, int total, void *user_data);
static void _Messenger(int message, int info, char *cinfo, void *user_data);
static int _gameInstaller(void *obj);
static int _GCgameInstaller(void *obj);
static int _GCcopyGame(void *obj);

View File

@ -71,6 +71,31 @@ void CMenu::_addDiscProgress(int status, int total, void *user_data)
}
}
void CMenu::_Messenger(int message, int info, char *cinfo, void *user_data)
{
CMenu &m = *(CMenu *)user_data;
LWP_MutexLock(m.m_mutex);
if(message == 1)
m._setThrdMsg(wfmt(m._fmt("wbfsop14", L"Calculating space needed for %s...\n Please insert disc %d to continue"), cinfo, info), 0.f);
if(message == 2)
m._setThrdMsg(wfmt(m._fmt("wbfsop15", L"Calculating space needed for %s"), cinfo), 0.f);
if(message == 3)
m._setThrdMsg(wfmt(m._fmt("wbfsop16", L"Installing %s"), cinfo), 0.f);
if(message == 4)
m._setThrdMsg(wfmt(m._fmt("wbfsop17", L"Installing %s disc %d/2"), cinfo, info), 0.f);
if(message == 5)
m._setThrdMsg(m._t("wbfsop18", L"Don't try to trick me with a Wii disc!!"), 0.f);
if(message == 6)
m._setThrdMsg(m._t("wbfsop19", L"This is not a GC disc!!"), 0.f);
if(message == 7)
m._setThrdMsg(wfmt(m._fmt("wbfsop20", L"You inserted disc %d again!!"), info), 0.f);
if(message == 8)
m._setThrdMsg(m._t("wbfsop21", L"This is a disc of another game!!"), 0.f);
if(message == 9)
m._setThrdMsg(wfmt(m._fmt("wbfsop22", L"Installing %s...\n Please insert disc 2 to continue"), cinfo), 1.f);
LWP_MutexUnlock(m.m_mutex);
}
int CMenu::_gameInstaller(void *obj)
{
CMenu &m = *(CMenu *)obj;
@ -144,7 +169,13 @@ int CMenu::_GCgameInstaller(void *obj)
u64 free = (u64)stats.f_frsize * (u64)stats.f_bfree;
u32 needed = 0;
m_gcdump.CheckSpace(&needed, comp);
ret = m_gcdump.CheckSpace(&needed, comp, CMenu::_Messenger, obj);
if(ret != 0)
{
m._setThrdMsg(m._t("wbfsop9", L"An error has occurred"), 1.f);
m.m_thrdWorking = false;
return ret;
}
u32 blockfree = free/0x8000;
@ -161,14 +192,14 @@ int CMenu::_GCgameInstaller(void *obj)
m._setThrdMsg(L"", 0);
LWP_MutexUnlock(m.m_mutex);
ret = m_gcdump.DumpGame(CMenu::_addDiscProgress, obj);
ret = m_gcdump.DumpGame(CMenu::_addDiscProgress, CMenu::_Messenger, obj);
LWP_MutexLock(m.m_mutex);
if(ret == 0)
m._setThrdMsg(m._t("wbfsop8", L"Game installed"), 1.f);
else if( ret >= 0x30200)
m._setThrdMsg(wfmt(m._fmt("wbfsop12", L"DVDError(%d)"), ret), 0.f);
m._setThrdMsg(wfmt(m._fmt("wbfsop12", L"DVDError(%d)"), ret), 1.f);
else if( ret > 0)
m._setThrdMsg(wfmt(m._fmt("wbfsop13", L"Game installed, but disc contains errors (%d)"), ret), 0.f);
m._setThrdMsg(wfmt(m._fmt("wbfsop13", L"Game installed, but disc contains errors (%d)"), ret), 1.f);
else
m._setThrdMsg(m._t("wbfsop9", L"An error has occurred"), 1.f);
LWP_MutexUnlock(m.m_mutex);