mirror of
https://github.com/Fledge68/WiiFlow_Lite.git
synced 2024-11-23 19:59:16 +01:00
* Updated DML Ex Gamecube disc dumper:
- Added retry on read errors - Added skipping on read errors - Added pos to compress data - Added pos to align all files by 32k - Dumper will now only dump game.iso on default - Now using drivebay led to show disc reading activity - Now checking if game already exists before dumping it Configuration of the dumper: Set the following vars in wiiflow.ini (domain: DML) to config the dumper: - skip_on_error=yes/no to enable/disable error skipping (default = no) - compressed_dump=yes/no to enable/disable compressed dumping (default = no) - write_ex_files=yes/no write ex files yes/no (default = no) - align_files=yes/no to align all by 32k yes/no (default = no) - num_retries=# were # = the amount of read retries the dumper should perform before it marks the block as bad on read errors
This commit is contained in:
parent
7a881364a0
commit
af589b404e
@ -1,8 +1,33 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2012
|
||||
* by OverjoY for Wiiflow
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any
|
||||
* damages arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any
|
||||
* purpose, including commercial applications, and to alter it and
|
||||
* redistribute it freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you
|
||||
* must not claim that you wrote the original software. If you use
|
||||
* this software in a product, an acknowledgment in the product
|
||||
* documentation would be appreciated but is not required.
|
||||
*
|
||||
* 2. Altered source versions must be plainly marked as such, and
|
||||
* must not be misrepresented as being the original software.
|
||||
*
|
||||
* 3. This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*
|
||||
* gc_disc.cpp
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <malloc.h>
|
||||
#include <ogcsys.h>
|
||||
#include <dirent.h>
|
||||
#include <sys/statvfs.h>
|
||||
|
||||
#include "gc_disc.hpp"
|
||||
@ -11,68 +36,342 @@
|
||||
#include "utils.h"
|
||||
#include "wdvd.h"
|
||||
#include "text.hpp"
|
||||
#include "gecko.h"
|
||||
|
||||
s32 __DiscReadRaw(void *outbuf, u32 offset, u32 length)
|
||||
static u8 *FSTable ALIGNED(32);
|
||||
|
||||
s32 GCDump::__DiscReadRaw(void *outbuf, u32 offset, u32 length)
|
||||
{
|
||||
return WDVD_UnencryptedRead(outbuf, length, offset);
|
||||
while(1)
|
||||
{
|
||||
*(u32*)0xCD0000C0 |= 0x20;
|
||||
gc_error = 0;
|
||||
s32 ret = WDVD_UnencryptedRead(outbuf, length, offset);
|
||||
if( ret != 0 )
|
||||
{
|
||||
WDVD_LowRequestError(&gc_error);
|
||||
if(gc_error == 0x30200 || gc_error == 0x30201 || gc_error == 0x31100)
|
||||
{
|
||||
if(gc_retry >= gc_nbrretry)
|
||||
{
|
||||
if(!skiponerror)
|
||||
{
|
||||
*(u32*)0xCD0000C0 &= ~0x20;
|
||||
return gc_error;
|
||||
}
|
||||
else
|
||||
{
|
||||
gc_retry = 0;
|
||||
gc_skipped++;
|
||||
gprintf("Read error (%x) at offset: 0x%08x. Skipping %d bytes\n", gc_error, offset, length);
|
||||
*(u32*)0xCD0000C0 &= ~0x20;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
gc_retry++;
|
||||
}
|
||||
else
|
||||
{
|
||||
gprintf("Read error(%x) at offset: 0x%08x.\n", gc_error, offset);
|
||||
*(u32*)0xCD0000C0 &= ~0x20;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
*(u32*)0xCD0000C0 &= ~0x20;
|
||||
gc_retry = 0;
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
s32 GC_GameDumper(progress_callback_t spinner, void *spinner_data)
|
||||
s32 GCDump::__DiscWrite(char * path, u32 offset, u32 length, progress_callback_t spinner, void *spinner_data)
|
||||
{
|
||||
gprintf("__DiscWrite(%s, 0x%08x, %x)\n", path, offset, length);
|
||||
u8 *ReadBuffer = (u8 *)memalign(32, gc_readsize);
|
||||
u32 toread = 0;
|
||||
u32 wrote = 0;
|
||||
FILE *f = fopen(path, "ab");
|
||||
|
||||
while(length)
|
||||
{
|
||||
toread = gc_readsize;
|
||||
if(toread > length)
|
||||
toread = length;
|
||||
|
||||
s32 ret = __DiscReadRaw(ReadBuffer, offset, (toread+31)&(~31));
|
||||
if( ret == 1 )
|
||||
memset(ReadBuffer, 0, gc_readsize);
|
||||
|
||||
else if( ret > 1 )
|
||||
return 0;
|
||||
|
||||
fwrite(ReadBuffer, 1, toread, f);
|
||||
|
||||
wrote += toread;
|
||||
offset += toread;
|
||||
length -= toread;
|
||||
if(spinner)
|
||||
spinner(wrote, DiscSize, spinner_data);
|
||||
}
|
||||
|
||||
fclose(f);
|
||||
free(ReadBuffer);
|
||||
return wrote;
|
||||
}
|
||||
|
||||
s32 GCDump::__DiscWriteAligned(char * path, u32 offset, u32 length)
|
||||
{
|
||||
u8 *ReadBuffer = (u8 *)memalign(32, gc_readsize+4);
|
||||
u32 toread = 0;
|
||||
u32 wrote = 0;
|
||||
FILE *f = fopen(path, "ab");
|
||||
|
||||
while(length)
|
||||
{
|
||||
toread = gc_readsize;
|
||||
if(toread > length)
|
||||
toread = length;
|
||||
|
||||
s32 ret = __DiscReadRaw(ReadBuffer, offset, (toread+31)&(~31));
|
||||
if( ret == 1 )
|
||||
memset(ReadBuffer, 0, gc_readsize);
|
||||
|
||||
|
||||
if( ret > 1 )
|
||||
return -1;
|
||||
|
||||
if(aligned)
|
||||
{
|
||||
fwrite(ReadBuffer, 1, (toread+31)&(~31), f);
|
||||
wrote += (toread+31)&(~31);
|
||||
}
|
||||
else
|
||||
{
|
||||
fwrite(ReadBuffer, 1, (toread+3)&(~3), f);
|
||||
wrote += (toread+3)&(~3);
|
||||
}
|
||||
offset += toread;
|
||||
length -= toread;
|
||||
}
|
||||
|
||||
fclose(f);
|
||||
free(ReadBuffer);
|
||||
return wrote;
|
||||
}
|
||||
|
||||
s32 GCDump::DumpGame(progress_callback_t spinner, void *spinner_data)
|
||||
{
|
||||
static gc_discHdr gcheader ATTRIBUTE_ALIGN(32);
|
||||
|
||||
FILE *f;
|
||||
u8 *ReadBuffer = (u8 *)memalign(32, READSIZE);
|
||||
u32 DiscSec = 0;
|
||||
u8 *ReadBuffer = (u8 *)memalign(32, 0x40);
|
||||
u8 *FSTBuffer;
|
||||
u32 wrote = 0;
|
||||
|
||||
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);
|
||||
|
||||
Disc_ReadGCHeader(&gcheader);
|
||||
s32 ret = Disc_ReadGCHeader(&gcheader);
|
||||
Asciify2(gcheader.title);
|
||||
|
||||
snprintf(folder, sizeof(folder), "%s:/games/%s [%s]", DeviceName[SD], gcheader.title, (char *)gcheader.id);
|
||||
makedir((char *)folder);
|
||||
|
||||
snprintf(gamepath, sizeof(gamepath), "%s/game.iso", folder);
|
||||
f = fopen(gamepath, "wb");
|
||||
while( DiscSec < 0xAE0B )
|
||||
if(writeexfiles)
|
||||
{
|
||||
__DiscReadRaw(ReadBuffer, DiscSec*READSIZE, READSIZE);
|
||||
fwrite(ReadBuffer, 1, READSIZE, f);
|
||||
spinner(DiscSec, 0xAE0B, spinner_data);
|
||||
DiscSec++;
|
||||
snprintf(folder, sizeof(folder), "%s:/games/%s [%s]/sys", DeviceName[SD], gcheader.title, (char *)gcheader.id);
|
||||
makedir((char *)folder);
|
||||
}
|
||||
fclose(f);
|
||||
|
||||
snprintf(folder, sizeof(folder), "%s:/games/%s [%s]/sys", DeviceName[SD], gcheader.title, (char *)gcheader.id);
|
||||
makedir((char *)folder);
|
||||
snprintf(gamepath, sizeof(gamepath), "%s/boot.bin", folder);
|
||||
__DiscReadRaw(ReadBuffer, 0, 0x440);
|
||||
ret = __DiscReadRaw(ReadBuffer, 0x400, 0x40);
|
||||
if(ret > 0)
|
||||
return 0x31100;
|
||||
|
||||
f = fopen(gamepath, "wb");
|
||||
fwrite(ReadBuffer, 1, 0x440, f);
|
||||
fclose(f);
|
||||
|
||||
ApploaderSize = *(vu32*)(ReadBuffer+0x400);
|
||||
|
||||
snprintf(gamepath, sizeof(gamepath), "%s/bi2.bin", folder);
|
||||
__DiscReadRaw(ReadBuffer, 0x440, 0x2000);
|
||||
|
||||
f = fopen(gamepath, "wb");
|
||||
fwrite(ReadBuffer, 1, 0x2000, f);
|
||||
fclose(f);
|
||||
|
||||
snprintf(gamepath, sizeof(gamepath), "%s/apploader.img", folder);
|
||||
__DiscReadRaw(ReadBuffer, 0x2440, ApploaderSize);
|
||||
|
||||
f = fopen(gamepath, "wb");
|
||||
fwrite(ReadBuffer, 1, ApploaderSize, f);
|
||||
fclose(f);
|
||||
ApploaderSize = *(vu32*)(ReadBuffer);
|
||||
DOLOffset = *(vu32*)(ReadBuffer+0x20);
|
||||
FSTOffset = *(vu32*)(ReadBuffer+0x24);
|
||||
FSTSize = *(vu32*)(ReadBuffer+0x28);
|
||||
GamePartOffset = *(vu32*)(ReadBuffer+0x34);
|
||||
DataSize = *(vu32*)(ReadBuffer+0x38);
|
||||
|
||||
free(ReadBuffer);
|
||||
|
||||
DOLSize = FSTOffset - DOLOffset;
|
||||
DiscSize = DataSize + GamePartOffset;
|
||||
|
||||
FSTBuffer = (u8 *)memalign(32, (FSTSize+31)&(~31));
|
||||
|
||||
ret = __DiscReadRaw(FSTBuffer, FSTOffset, (FSTSize+31)&(~31));
|
||||
if(ret > 0)
|
||||
return 0x31100;
|
||||
|
||||
FSTable = (u8*)FSTBuffer;
|
||||
|
||||
FSTEnt = *(u32*)(FSTable+0x08);
|
||||
|
||||
FSTNameOff = (char*)(FSTable + FSTEnt * 0x0C);
|
||||
FST *fst = (FST *)(FSTable);
|
||||
|
||||
gprintf("Dumping: %s %s\n", gcheader.title, compressed ? "compressed" : "full");
|
||||
|
||||
gprintf("Apploader size : %d\n", ApploaderSize);
|
||||
gprintf("DOL offset : 0x%08x\n", DOLOffset);
|
||||
gprintf("DOL size : %d\n", DOLSize);
|
||||
gprintf("FST offset : 0x%08x\n", FSTOffset);
|
||||
gprintf("FST size : %d\n", FSTSize);
|
||||
gprintf("Num FST entries: %d\n", FSTEnt);
|
||||
gprintf("Disc size : %d\n", DiscSize);
|
||||
|
||||
if(writeexfiles)
|
||||
{
|
||||
gprintf("Writing %s/boot.bin\n", folder);
|
||||
snprintf(gamepath, sizeof(gamepath), "%s/boot.bin", folder);
|
||||
__DiscWrite(gamepath, 0, 0x440, spinner, spinner_data);
|
||||
|
||||
gprintf("Writing %s/bi2.bin\n", folder);
|
||||
snprintf(gamepath, sizeof(gamepath), "%s/bi2.bin", folder);
|
||||
__DiscWrite(gamepath, 0x440, 0x2000, spinner, spinner_data);
|
||||
|
||||
gprintf("Writing %s/apploader.img\n", folder);
|
||||
snprintf(gamepath, sizeof(gamepath), "%s/apploader.img", folder);
|
||||
__DiscWrite(gamepath, 0x2440, ApploaderSize, spinner, spinner_data);
|
||||
}
|
||||
|
||||
snprintf(gamepath, sizeof(gamepath), "%s:/games/%s [%s]/game.iso", DeviceName[SD], gcheader.title, (char *)gcheader.id);
|
||||
|
||||
gprintf("Writing %s\n", gamepath);
|
||||
if(compressed)
|
||||
{
|
||||
ret = __DiscWriteAligned(gamepath, 0, GamePartOffset);
|
||||
wrote += ret;
|
||||
|
||||
u32 i;
|
||||
|
||||
for( i=1; i < FSTEnt; ++i )
|
||||
{
|
||||
if( fst[i].Type )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = __DiscWriteAligned(gamepath, fst[i].FileOffset, fst[i].FileLength);
|
||||
gprintf("Writing: %d/%d: %s from 0x%08x to 0x%08x\n", i, FSTEnt, FSTNameOff + fst[i].NameOffset, fst[i].FileOffset, wrote);
|
||||
if( ret >= 0 )
|
||||
{
|
||||
fst[i].FileOffset = wrote;
|
||||
wrote += ret;
|
||||
spinner(i, FSTEnt, spinner_data);
|
||||
}
|
||||
else
|
||||
{
|
||||
spinner(FSTEnt, FSTEnt, spinner_data);
|
||||
free(FSTBuffer);
|
||||
return gc_error;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
gprintf("Updating FST\n");
|
||||
|
||||
FILE *f = fopen(gamepath, "r+");
|
||||
fseek(f, FSTOffset, SEEK_SET);
|
||||
fwrite(fst, 1, FSTSize, f);
|
||||
fclose(f);
|
||||
|
||||
gprintf("Done!! Disc old size: %d, disc new size: %d, saved: %d\n", DiscSize, wrote, DiscSize - wrote);
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = __DiscWrite(gamepath, 0, DiscSize, spinner, spinner_data);
|
||||
if( ret < 0 )
|
||||
{
|
||||
free(FSTBuffer);
|
||||
return gc_error;
|
||||
}
|
||||
gprintf("Done!! Disc size: %d\n", DiscSize);
|
||||
}
|
||||
|
||||
free(FSTBuffer);
|
||||
|
||||
return gc_skipped;
|
||||
}
|
||||
|
||||
s32 GCDump::CheckSpace(u32 *needed, bool comp)
|
||||
{
|
||||
u8 *ReadBuffer = (u8 *)memalign(32, 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;
|
||||
|
||||
free(ReadBuffer);
|
||||
|
||||
u32 size = 0;
|
||||
|
||||
if(writeexfiles)
|
||||
{
|
||||
size += 0xa440;
|
||||
size += ApploaderSize;
|
||||
}
|
||||
|
||||
if(!comp)
|
||||
{
|
||||
size += DiscSize;
|
||||
}
|
||||
else
|
||||
{
|
||||
u8 *FSTBuffer = (u8 *)memalign(32, (FSTSize+31)&(~31));
|
||||
|
||||
ret = __DiscReadRaw(FSTBuffer, FSTOffset, (FSTSize+31)&(~31));
|
||||
if(ret > 0)
|
||||
{
|
||||
free(FSTBuffer);
|
||||
return 1;
|
||||
}
|
||||
|
||||
FSTable = (u8*)FSTBuffer;
|
||||
u32 FSTEnt = *(u32*)(FSTable+0x08);
|
||||
FST *fst = (FST *)(FSTable);
|
||||
|
||||
u32 i;
|
||||
|
||||
for( i=1; i < FSTEnt; ++i )
|
||||
{
|
||||
if( fst[i].Type )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
size += (fst[i].FileLength+31)&(~31);
|
||||
}
|
||||
}
|
||||
free(FSTBuffer);
|
||||
}
|
||||
*needed = size/0x8000;
|
||||
gprintf("Free space needed on SD: %d bytes (%x blocks)\n", size, size/0x8000);
|
||||
return 0;
|
||||
}
|
@ -1,9 +1,89 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2012
|
||||
* by OverjoY for Wiiflow
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any
|
||||
* damages arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any
|
||||
* purpose, including commercial applications, and to alter it and
|
||||
* redistribute it freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you
|
||||
* must not claim that you wrote the original software. If you use
|
||||
* this software in a product, an acknowledgment in the product
|
||||
* documentation would be appreciated but is not required.
|
||||
*
|
||||
* 2. Altered source versions must be plainly marked as such, and
|
||||
* must not be misrepresented as being the original software.
|
||||
*
|
||||
* 3. This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*
|
||||
* gc_disc.hpp
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef GC_DISC_H_
|
||||
#define GC_DISC_H_
|
||||
|
||||
typedef void (*progress_callback_t)(int status,int total,void *user_data);
|
||||
|
||||
s32 GC_GameDumper(progress_callback_t spinner, void *spinner_data);
|
||||
s32 GC_DiskSpace(u64 *free);
|
||||
|
||||
class GCDump
|
||||
{
|
||||
public:
|
||||
void Init(bool skip, bool comp, bool wexf, bool align, u32 nretry, u32 rsize)
|
||||
{
|
||||
skiponerror = skip;
|
||||
compressed = comp;
|
||||
writeexfiles = wexf;
|
||||
aligned = align;
|
||||
gc_nbrretry = nretry;
|
||||
gc_readsize = rsize;
|
||||
gc_skipped = 0;
|
||||
}
|
||||
s32 DumpGame(progress_callback_t spinner, void *spinner_data);
|
||||
s32 CheckSpace(u32 *needed, bool comp);
|
||||
private:
|
||||
bool aligned;
|
||||
bool skiponerror;
|
||||
bool compressed;
|
||||
bool writeexfiles;
|
||||
u32 gc_nbrretry;
|
||||
u32 gc_error;
|
||||
u32 gc_retry;
|
||||
u32 gc_skipped;
|
||||
u32 gc_readsize;
|
||||
u32 DiscSize;
|
||||
typedef struct
|
||||
{
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
u32 Type :8;
|
||||
u32 NameOffset :24;
|
||||
};
|
||||
u32 TypeName;
|
||||
};
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
u32 FileOffset;
|
||||
u32 FileLength;
|
||||
};
|
||||
struct
|
||||
{
|
||||
u32 ParentOffset;
|
||||
u32 NextOffset;
|
||||
};
|
||||
u32 entry[2];
|
||||
};
|
||||
} FST;
|
||||
s32 __DiscReadRaw(void *outbuf, u32 offset, u32 length);
|
||||
s32 __DiscWrite(char * path, u32 offset, u32 length, progress_callback_t spinner , void *spinner_data);
|
||||
s32 __DiscWriteAligned(char * path, u32 offset, u32 length);
|
||||
};
|
||||
#endif
|
@ -7,7 +7,6 @@
|
||||
#define MB_SIZE 1048576.0
|
||||
#define GB_SIZE 1073741824.0
|
||||
|
||||
#define READSIZE (32*1024)
|
||||
#define MAX_FAT_PATH 1024
|
||||
|
||||
/* Macros */
|
||||
@ -15,6 +14,7 @@
|
||||
|
||||
#define ALIGN(x) (((x) + 3) & ~3)
|
||||
#define ALIGN32(x) (((x) + 31) & ~31)
|
||||
#define ALIGNED(x) __attribute__((aligned(x)))
|
||||
|
||||
#define SMART_FREE(P) {if(!!P)P.release();}
|
||||
#define SAFE_FREE(P) {if(P != NULL){free(P);P = NULL;}}
|
||||
|
@ -5,25 +5,26 @@
|
||||
#include "gecko.h"
|
||||
|
||||
/* Constants */
|
||||
#define IOCTL_DI_READID 0x70
|
||||
#define IOCTL_DI_READ 0x71
|
||||
#define IOCTL_DI_WAITCVRCLOSE 0x79
|
||||
#define IOCTL_DI_GETCOVER 0x88
|
||||
#define IOCTL_DI_RESET 0x8A
|
||||
#define IOCTL_DI_OPENPART 0x8B
|
||||
#define IOCTL_DI_CLOSEPART 0x8C
|
||||
#define IOCTL_DI_UNENCREAD 0x8D
|
||||
#define IOCTL_DI_SEEK 0xAB
|
||||
#define IOCTL_DI_STOPLASER 0xD2
|
||||
#define IOCTL_DI_OFFSET 0xD9
|
||||
#define IOCTL_DI_DISC_BCA 0xDA
|
||||
#define IOCTL_DI_STOPMOTOR 0xE3
|
||||
#define IOCTL_DI_SETWBFSMODE 0xF4
|
||||
#define IOCTL_DI_READID 0x70
|
||||
#define IOCTL_DI_READ 0x71
|
||||
#define IOCTL_DI_WAITCVRCLOSE 0x79
|
||||
#define IOCTL_DI_GETCOVER 0x88
|
||||
#define IOCTL_DI_RESET 0x8A
|
||||
#define IOCTL_DI_OPENPART 0x8B
|
||||
#define IOCTL_DI_CLOSEPART 0x8C
|
||||
#define IOCTL_DI_UNENCREAD 0x8D
|
||||
#define IOCTL_DI_SEEK 0xAB
|
||||
#define IOCTL_DI_STOPLASER 0xD2
|
||||
#define IOCTL_DI_OFFSET 0xD9
|
||||
#define IOCTL_DI_DISC_BCA 0xDA
|
||||
#define IOCTL_DI_REQUESTERROR 0xE0
|
||||
#define IOCTL_DI_STOPMOTOR 0xE3
|
||||
#define IOCTL_DI_SETWBFSMODE 0xF4
|
||||
#define IOCTL_DI_DVDLowAudioBufferConfig 0xE4
|
||||
|
||||
#define IOCTL_DI_SETFRAG 0xF9
|
||||
#define IOCTL_DI_GETMODE 0xFA
|
||||
#define IOCTL_DI_HELLO 0xFB
|
||||
#define IOCTL_DI_SETFRAG 0xF9
|
||||
#define IOCTL_DI_GETMODE 0xFA
|
||||
#define IOCTL_DI_HELLO 0xFB
|
||||
|
||||
/* Variables */
|
||||
static u32 inbuf[8] ATTRIBUTE_ALIGN(32);
|
||||
@ -271,6 +272,21 @@ s32 WDVD_Read(void *buf, u32 len, u64 offset)
|
||||
return (ret == 1) ? 0 : -ret;
|
||||
}
|
||||
|
||||
s32 WDVD_LowRequestError(u32 *error)
|
||||
{
|
||||
memset(inbuf, 0, sizeof(inbuf));
|
||||
|
||||
inbuf[0] = IOCTL_DI_REQUESTERROR << 24;
|
||||
|
||||
s32 ret = IOS_Ioctl(di_fd, IOCTL_DI_REQUESTERROR, inbuf, sizeof(inbuf), outbuf, sizeof(outbuf));
|
||||
if (ret < 0) return ret;
|
||||
|
||||
if (ret == 1)
|
||||
memcpy(error, outbuf, sizeof(u32));
|
||||
|
||||
return (ret == 1) ? 0 : -ret;
|
||||
}
|
||||
|
||||
s32 WDVD_WaitForDisc(void)
|
||||
{
|
||||
memset(inbuf, 0, sizeof(inbuf));
|
||||
|
@ -19,6 +19,7 @@ s32 WDVD_OpenPartition(u64 offset, void* Ticket, void* Certificate, unsigned int
|
||||
s32 WDVD_ClosePartition(void);
|
||||
s32 WDVD_UnencryptedRead(void *, u32, u64);
|
||||
s32 WDVD_Read(void *, u32, u64);
|
||||
s32 WDVD_LowRequestError(u32 *error);
|
||||
s32 WDVD_WaitForDisc(void);
|
||||
s32 WDVD_GetCoverStatus(u32 *);
|
||||
s32 WDVD_SetUSBMode(u32, const u8 *, s32);
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include "gct.h"
|
||||
#include "DeviceHandler.hpp"
|
||||
#include "musicplayer.h"
|
||||
#include "loader/gc_disc.hpp"
|
||||
|
||||
//Also in wbfs.h
|
||||
#define PART_FS_WBFS 0
|
||||
@ -66,6 +67,7 @@ private:
|
||||
Config m_titles;
|
||||
Config m_version;
|
||||
Channels m_channels;
|
||||
GCDump m_gcdump;
|
||||
safe_vector<std::string> m_homebrewArgs;
|
||||
SmartBuf m_base_font;
|
||||
u32 m_base_font_size;
|
||||
|
@ -110,6 +110,15 @@ int CMenu::_GCgameInstaller(void *obj)
|
||||
{
|
||||
CMenu &m = *(CMenu *)obj;
|
||||
|
||||
bool skip = m.m_cfg.getBool("DML", "skip_on_error", false);
|
||||
bool comp = m.m_cfg.getBool("DML", "compressed_dump", false);
|
||||
bool wexf = m.m_cfg.getBool("DML", "write_ex_files", false);
|
||||
bool alig = m.m_cfg.getBool("DML", "align_files", false);
|
||||
u32 nretry = m.m_cfg.getUInt("DML", "num_retries", 5);
|
||||
u32 rsize = 32768;
|
||||
|
||||
m.m_gcdump.Init(skip, comp, wexf, alig, nretry, rsize);
|
||||
|
||||
int ret;
|
||||
|
||||
if (!DeviceHandler::Instance()->IsInserted(SD))
|
||||
@ -123,29 +132,33 @@ int CMenu::_GCgameInstaller(void *obj)
|
||||
statvfs("sd:/" , &stats);
|
||||
|
||||
u64 free = (u64)stats.f_frsize * (u64)stats.f_bfree;
|
||||
u32 needed = 0;
|
||||
|
||||
int blockfree = free/0x8000;
|
||||
m.m_gcdump.CheckSpace(&needed, comp);
|
||||
|
||||
if (blockfree <= 44556)
|
||||
u32 blockfree = free/0x8000;
|
||||
|
||||
if (blockfree <= needed)
|
||||
{
|
||||
LWP_MutexLock(m.m_mutex);
|
||||
m._setThrdMsg(wfmt(m._fmt("wbfsop11", L"Not enough space : 44557 blocks needed, %d available"), blockfree), 0.f);
|
||||
m._setThrdMsg(wfmt(m._fmt("wbfsop11", L"Not enough space : %d blocks needed, %d available"), needed, blockfree), 0.f);
|
||||
LWP_MutexUnlock(m.m_mutex);
|
||||
ret = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
LWP_MutexLock(m.m_mutex);
|
||||
m._setThrdMsg(L"", 0);
|
||||
LWP_MutexUnlock(m.m_mutex);
|
||||
|
||||
ret=0;
|
||||
|
||||
ret = GC_GameDumper(CMenu::_addDiscProgress, obj);
|
||||
ret = m.m_gcdump.DumpGame(CMenu::_addDiscProgress, obj);
|
||||
LWP_MutexLock(m.m_mutex);
|
||||
if (ret == 0)
|
||||
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);
|
||||
else if( ret > 0)
|
||||
m._setThrdMsg(wfmt(m._fmt("wbfsop13", L"Game installed, but disc contains errors (%d)"), ret), 0.f);
|
||||
else
|
||||
m._setThrdMsg(m._t("wbfsop9", L"An error has occurred"), 1.f);
|
||||
LWP_MutexUnlock(m.m_mutex);
|
||||
@ -243,6 +256,13 @@ bool CMenu::_wbfsOp(CMenu::WBFS_OP op)
|
||||
else if(Disc_IsGC() == 0)
|
||||
{
|
||||
Disc_ReadGCHeader(&gcheader);
|
||||
|
||||
if (_searchGamesByID((const char *) gcheader.id).size() != 0)
|
||||
{
|
||||
error(_t("wbfsoperr4", L"Game already installed"));
|
||||
out = true;
|
||||
break;
|
||||
}
|
||||
cfPos = string((char *) gcheader.id);
|
||||
m_btnMgr.setText(m_wbfsLblDialog, wfmt(_fmt("wbfsop6", L"Installing [%s] %s..."), string((const char *)gcheader.id, sizeof gcheader.id).c_str(), string((const char *)gcheader.title, sizeof gcheader.title).c_str()));
|
||||
done = true;
|
||||
|
Loading…
Reference in New Issue
Block a user