usbloadergx/source/usbloader/wbfs/wbfs_fat.cpp
dimok321 f3ef9104b1 *Whole lot of cleanup in the cfg.c
*Moved all related global settings to a settings class. one for themes and individual games will follow. Probably broke some settings or theme loading, we can deal with that later and fix when someone discovers bugs.
2010-09-19 20:25:12 +00:00

932 lines
25 KiB
C++

// WBFS FAT by oggzee
#include <stdio.h>
#include <unistd.h>
#include <malloc.h>
#include <ogcsys.h>
#include <dirent.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/statvfs.h>
#include <ctype.h>
#include "settings/CSettings.h"
#include "usbloader/disc.h"
#include "fatmounter.h"
#include "wbfs_fat.h"
#include "prompts/ProgressWindow.h"
#include "wbfs_rw.h"
#include "gecko.h"
#define MAX_FAT_PATH 1024
#define TITLE_LEN 64
using namespace std;
char Wbfs_Fat::wbfs_fs_drive[16];
char Wbfs_Fat::wbfs_fat_dir[16] = "/wbfs";
char Wbfs_Fat::invalid_path[] = "/\\:|<>?*\"'";
struct discHdr *Wbfs_Fat::fat_hdr_list = NULL;
u32 Wbfs_Fat::fat_hdr_count = 0;
extern "C"
{
int _FAT_get_fragments ( const char *path, _frag_append_t append_fragment, void *callback_data );
extern FragList *frag_list;
}
u32 Wbfs_Fat::fat_sector_size = 512;
Wbfs_Fat::Wbfs_Fat( u32 device, u32 lba, u32 size ) : Wbfs( device, lba, size )
{
}
s32 Wbfs_Fat::Open()
{
if ( device == WBFS_DEVICE_USB && lba == fat_usb_sec )
{
strcpy( wbfs_fs_drive, "USB:" );
}
else if ( device == WBFS_DEVICE_SDHC && lba == fat_sd_sec )
{
strcpy( wbfs_fs_drive, "SD:" );
}
else
{
if ( WBFSDevice_Init( lba ) ) return -1;
strcpy( wbfs_fs_drive, "WBFS:" );
}
return 0;
}
wbfs_disc_t* Wbfs_Fat::OpenDisc( u8 *discid )
{
char fname[MAX_FAT_PATH];
// wbfs 'partition' file
if ( !FindFilename( discid, fname, sizeof( fname ) ) ) return NULL;
if ( strcasecmp( strrchr( fname, '.' ), ".iso" ) == 0 )
{
// .iso file
// create a fake wbfs_disc
int fd;
fd = open( fname, O_RDONLY );
if ( fd == -1 ) return NULL;
wbfs_disc_t *iso_file = ( wbfs_disc_t * )calloc( sizeof( wbfs_disc_t ), 1 );
if ( iso_file == NULL ) return NULL;
// mark with a special wbfs_part
wbfs_iso_file.wbfs_sec_sz = 512;
iso_file->p = &wbfs_iso_file;
iso_file->header = ( wbfs_disc_info_t* )fd;
return iso_file;
}
wbfs_t *part = OpenPart( fname );
if ( !part ) return NULL;
return wbfs_open_disc( part, discid );
}
void Wbfs_Fat::CloseDisc( wbfs_disc_t* disc )
{
if ( !disc ) return;
wbfs_t *part = disc->p;
// is this really a .iso file?
if ( part == &wbfs_iso_file )
{
close( ( int )disc->header );
free( disc );
return;
}
wbfs_close_disc( disc );
ClosePart( part );
return;
}
s32 Wbfs_Fat::GetCount( u32 *count )
{
*count = 0;
GetHeadersCount();
if ( fat_hdr_count && fat_hdr_list )
{
// for compacter mem - move up as it will be freed later
int size = fat_hdr_count * sizeof( struct discHdr );
struct discHdr *buf = ( struct discHdr * ) malloc( size );
if ( buf )
{
memcpy( buf, fat_hdr_list, size );
SAFE_FREE( fat_hdr_list );
fat_hdr_list = buf;
}
}
*count = fat_hdr_count;
return 0;
}
s32 Wbfs_Fat::GetHeaders( struct discHdr *outbuf, u32 cnt, u32 len )
{
u32 i;
if ( len > sizeof( struct discHdr ) )
{
len = sizeof( struct discHdr );
}
#ifdef DEBUG_WBFS
gprintf( "\n\tGetHeaders" );
#endif
for ( i = 0; i < cnt && i < fat_hdr_count; i++ )
{
memcpy( &outbuf[i], &fat_hdr_list[i], len );
}
SAFE_FREE( fat_hdr_list );
fat_hdr_count = 0;
#ifdef DEBUG_WBFS
gprintf( "...ok" );
#endif
return 0;
}
s32 Wbfs_Fat::AddGame( void )
{
static struct discHdr header ATTRIBUTE_ALIGN( 32 );
char path[MAX_FAT_PATH];
wbfs_t *part = NULL;
s32 ret;
// read ID from DVD
Disc_ReadHeader( &header );
// path
GetDir( &header, path );
// create wbfs 'partition' file
part = CreatePart( header.id, path );
if ( !part ) return -1;
/* Add game to device */
partition_selector_t part_sel = ALL_PARTITIONS;
int copy_1_1 = Settings.fullcopy;
switch ( Settings.partitions_to_install )
{
case install_game_only:
part_sel = ONLY_GAME_PARTITION;
break;
case install_all:
part_sel = ALL_PARTITIONS;
break;
case install_all_but_update:
part_sel = REMOVE_UPDATE_PARTITION;
break;
}
if ( copy_1_1 )
{
part_sel = ALL_PARTITIONS;
}
wbfs_t *old_hdd = hdd;
hdd = part; // used by spinner
ret = wbfs_add_disc( part, __ReadDVD, NULL, ProgressCallback, part_sel, copy_1_1 );
hdd = old_hdd;
wbfs_trim( part );
ClosePart( part );
if ( ret < 0 ) return ret;
mk_title_txt( &header, path );
return 0;
}
s32 Wbfs_Fat::RemoveGame( u8 *discid )
{
char fname[MAX_FAT_PATH];
int loc;
// wbfs 'partition' file
loc = FindFilename( discid, fname, sizeof( fname ) );
if ( !loc ) return -1;
split_create( &split, fname, 0, 0, true );
split_close( &split );
if ( loc == 1 ) return 0;
// game is in subdir
// remove optional .txt file
DIR_ITER *dir_iter;
struct stat st;
char path[MAX_FAT_PATH];
char name[MAX_FAT_PATH];
strncpy( path, fname, sizeof( path ) );
char *p = strrchr( path, '/' );
if ( p ) *p = 0;
dir_iter = diropen( path );
if ( !dir_iter ) return 0;
while ( dirnext( dir_iter, name, &st ) == 0 )
{
if ( name[0] == '.' ) continue;
if ( name[6] != '_' ) continue;
if ( strncmp( name, ( char* )discid, 6 ) != 0 ) continue;
p = strrchr( name, '.' );
if ( !p ) continue;
if ( strcasecmp( p, ".txt" ) != 0 ) continue;
snprintf( fname, sizeof( fname ), "%s/%s", path, name );
remove( fname );
break;
}
dirclose( dir_iter );
// remove game subdir
unlink( path );
return 0;
}
s32 Wbfs_Fat::DiskSpace( f32 *used, f32 *free )
{
f32 size;
int ret;
struct statvfs wbfs_fat_vfs;
*used = 0;
*free = 0;
ret = statvfs( wbfs_fs_drive, &wbfs_fat_vfs );
if ( ret ) return -1;
/* FS size in GB */
size = ( f32 )wbfs_fat_vfs.f_frsize * ( f32 )wbfs_fat_vfs.f_blocks / GB_SIZE;
*free = ( f32 )wbfs_fat_vfs.f_frsize * ( f32 )wbfs_fat_vfs.f_bfree / GB_SIZE;
*used = size - *free;
return 0;
}
s32 Wbfs_Fat::RenameGame( u8 *discid, const void *newname )
{
wbfs_t *part = OpenPart( ( char * ) discid );
if ( !part )
return -1;
s32 ret = wbfs_ren_disc( part, discid, ( u8* )newname );
ClosePart( part );
return ret;
}
s32 Wbfs_Fat::ReIDGame( u8 *discid, const void *newID )
{
wbfs_t *part = OpenPart( ( char * ) discid );
if ( !part )
return -1;
s32 ret = wbfs_rID_disc( part, discid, ( u8* )newID );
ClosePart( part );
if ( ret == 0 )
{
char fname[100];
char fnamenew[100];
s32 cnt = 0x31;
Filename( discid, fname, sizeof( fname ), NULL );
Filename( ( u8* ) newID, fnamenew, sizeof( fnamenew ), NULL );
int stringlength = strlen( fname );
while ( rename( fname, fnamenew ) == 0 )
{
fname[stringlength] = cnt;
fname[stringlength+1] = 0;
fnamenew[stringlength] = cnt;
fnamenew[stringlength+1] = 0;
cnt++;
}
}
return ret;
}
f32 Wbfs_Fat::EstimateGameSize()
{
wbfs_t *part = NULL;
u64 size = ( u64 )143432 * 2 * 0x8000ULL;
u32 n_sector = size / fat_sector_size;
u32 wii_sec_sz;
// init a temporary dummy part
// as a placeholder for wbfs_size_disc
part = wbfs_open_partition(
nop_rw_sector, nop_rw_sector,
NULL, fat_sector_size, n_sector, 0, 1 );
if ( !part ) return -1;
wii_sec_sz = part->wii_sec_sz;
partition_selector_t part_sel;
if ( Settings.fullcopy )
{
part_sel = ALL_PARTITIONS;
}
else
{
part_sel = Settings.partitions_to_install == install_game_only ? ONLY_GAME_PARTITION : ALL_PARTITIONS;
}
return wbfs_estimate_disc( part, __ReadDVD, NULL, part_sel );
}
// TITLE [GAMEID]
bool Wbfs_Fat::CheckLayoutB( char *fname, int len, u8* id, char *fname_title )
{
if ( len <= 8 ) return false;
if ( fname[len-8] != '[' || fname[len-1] != ']' ) return false;
if ( !is_gameid( &fname[len-7] ) ) return false;
strncpy( fname_title, fname, TITLE_LEN );
// cut at '['
fname_title[len-8] = 0;
int n = strlen( fname_title );
if ( n == 0 ) return false;
// cut trailing _ or ' '
if ( fname_title[n - 1] == ' ' || fname_title[n - 1] == '_' )
{
fname_title[n - 1] = 0;
}
if ( strlen( fname_title ) == 0 ) return false;
if ( id )
{
memcpy( id, &fname[len-7], 6 );
id[6] = 0;
}
return true;
}
s32 Wbfs_Fat::GetHeadersCount()
{
char path[MAX_FAT_PATH];
char fname[MAX_FAT_PATH];
char fpath[MAX_FAT_PATH];
struct discHdr tmpHdr;
struct stat st;
wbfs_t *part = NULL;
u8 id[8];
int ret;
char *p;
u32 size;
int is_dir;
int len;
char dir_title[65];
char fname_title[TITLE_LEN];
char *title;
DIR_ITER *dir_iter;
//dbg_time1();
SAFE_FREE( fat_hdr_list );
fat_hdr_count = 0;
strcpy( path, wbfs_fs_drive );
strcat( path, wbfs_fat_dir );
dir_iter = diropen( path );
if ( !dir_iter ) return 0;
dir_iter = diropen( path );
if ( !dir_iter ) return 0;
while ( dirnext( dir_iter, fname, &st ) == 0 )
{
//printf("found: %s\n", fname); Wpad_WaitButtonsCommon();
if ( ( char )fname[0] == '.' ) continue;
len = strlen( fname );
if ( len < 8 ) continue; // "GAMEID_x"
memcpy( id, fname, 6 );
id[6] = 0;
*fname_title = 0;
is_dir = S_ISDIR( st.st_mode );
//printf("mode: %d %d %x\n", is_dir, st.st_mode, st.st_mode);
if ( is_dir )
{
int lay_a = 0;
int lay_b = 0;
if ( fname[6] == '_' && is_gameid( ( char* )id ) )
{
// usb:/wbfs/GAMEID_TITLE/GAMEID.wbfs
lay_a = 1;
}
if ( CheckLayoutB( fname, len, NULL, fname_title ) )
{
// usb:/wbfs/TITLE[GAMEID]/GAMEID.wbfs
lay_b = 1;
}
if ( !lay_a && !lay_b ) continue;
if ( lay_a )
{
strncpy( dir_title, &fname[7], sizeof( dir_title ) );
}
else
{
try_lay_b:
if ( !CheckLayoutB( fname, len, id, fname_title ) ) continue;
}
snprintf( fpath, sizeof( fpath ), "%s/%s/%s.wbfs", path, fname, id );
//printf("path2: %s\n", fpath);
// if more than 50 games, skip second stat to improve speed
// but if ambiguous layout check anyway
if ( fat_hdr_count < 50 || ( lay_a && lay_b ) )
{
if ( stat( fpath, &st ) == -1 )
{
//printf("missing: %s\n", fpath);
// try .iso
strcpy( strrchr( fpath, '.' ), ".iso" ); // replace .wbfs with .iso
if ( stat( fpath, &st ) == -1 )
{
//printf("missing: %s\n", fpath);
// try .ciso
strcpy( strrchr( fpath, '.' ), ".ciso" ); // replace .iso with .ciso
if ( stat( fpath, &st ) == -1 )
{
if ( lay_a && lay_b == 1 )
{
// mark lay_b so that the stat check is still done,
// but lay_b is not re-tried again
lay_b = 2;
// retry with layout b
goto try_lay_b;
}
continue;
}
}
}
}
else
{
st.st_size = 1024 * 1024;
}
}
else
{
// usb:/wbfs/GAMEID.wbfs
// or usb:/wbfs/GAMEID.iso
// or usb:/wbfs/GAMEID.ciso
p = strrchr( fname, '.' );
if ( !p ) continue;
if ( ( strcasecmp( p, ".wbfs" ) != 0 )
&& ( strcasecmp( p, ".iso" ) != 0 )
&& ( strcasecmp( p, ".ciso" ) != 0 ) ) continue;
int n = p - fname; // length withouth .wbfs
if ( n != 6 )
{
// TITLE [GAMEID].wbfs
if ( !CheckLayoutB( fname, n, id, fname_title ) ) continue;
}
snprintf( fpath, sizeof( fpath ), "%s/%s", path, fname );
}
//printf("found: %s %d MB\n", fpath, (int)(st.st_size/1024/1024));
// size must be at least 1MB to be considered a valid wbfs file
if ( st.st_size < 1024*1024 ) continue;
// if we have titles.txt entry use that
title = cfg_get_title( id );
// if no titles.txt get title from dir or file name
if ( !title && *fname_title )
{
title = fname_title;
}
if ( title )
{
memset( &tmpHdr, 0, sizeof( tmpHdr ) );
memcpy( tmpHdr.id, id, 6 );
strncpy( tmpHdr.title, title, sizeof( tmpHdr.title ) - 1 );
tmpHdr.magic = 0x5D1C9EA3;
goto add_hdr;
}
// else read it from file directly
if ( strcasecmp( strrchr( fpath, '.' ), ".wbfs" ) == 0 )
{
// wbfs file directly
FILE *fp = fopen( fpath, "rb" );
if ( fp != NULL )
{
fseek( fp, 512, SEEK_SET );
fread( &tmpHdr, sizeof( struct discHdr ), 1, fp );
fclose( fp );
tmpHdr.is_ciso = 0;
if ( ( tmpHdr.magic == 0x5D1C9EA3 ) && ( memcmp( tmpHdr.id, id, 6 ) == 0 ) )
{
goto add_hdr;
}
}
// no title found, read it from wbfs file
// but this is a little bit slower
// open 'partition' file
part = OpenPart( fpath );
if ( !part )
{
continue;
}
// Get header
ret = wbfs_get_disc_info( part, 0, ( u8* ) & tmpHdr,
sizeof( struct discHdr ), &size );
ClosePart( part );
if ( ret == 0 )
{
goto add_hdr;
}
}
else if ( strcasecmp( strrchr( fpath, '.' ), ".iso" ) == 0 )
{
// iso file
FILE *fp = fopen( fpath, "rb" );
if ( fp != NULL )
{
fseek( fp, 0, SEEK_SET );
fread( &tmpHdr, sizeof( struct discHdr ), 1, fp );
fclose( fp );
tmpHdr.is_ciso = 0;
if ( ( tmpHdr.magic == 0x5D1C9EA3 ) && ( memcmp( tmpHdr.id, id, 6 ) == 0 ) )
{
goto add_hdr;
}
}
}
else if ( strcasecmp( strrchr( fpath, '.' ), ".ciso" ) == 0 )
{
// ciso file
FILE *fp = fopen( fpath, "rb" );
if ( fp != NULL )
{
fseek( fp, 0x8000, SEEK_SET );
fread( &tmpHdr, sizeof( struct discHdr ), 1, fp );
fclose( fp );
tmpHdr.is_ciso = 1;
if ( ( tmpHdr.magic == 0x5D1C9EA3 ) && ( memcmp( tmpHdr.id, id, 6 ) == 0 ) )
{
goto add_hdr;
}
}
}
// fail:
continue;
// succes: add tmpHdr to list:
add_hdr:
memset( &st, 0, sizeof( st ) );
//printf("added: %.6s %.20s\n", tmpHdr.id, tmpHdr.title); Wpad_WaitButtons();
fat_hdr_count++;
fat_hdr_list = ( struct discHdr * ) realloc( fat_hdr_list, fat_hdr_count * sizeof( struct discHdr ) );
memcpy( &fat_hdr_list[fat_hdr_count-1], &tmpHdr, sizeof( struct discHdr ) );
}
dirclose( dir_iter );
//dbg_time2("\nFAT_GetCount"); Wpad_WaitButtonsCommon();
return 0;
}
int Wbfs_Fat::FindFilename( u8 *id, char *fname, int len )
{
struct stat st;
// look for direct .wbfs file
Filename( id, fname, len, NULL );
if ( stat( fname, &st ) == 0 ) return 1;
// look for direct .iso file
strcpy( strrchr( fname, '.' ), ".iso" ); // replace .wbfs with .iso
if ( stat( fname, &st ) == 0 ) return 1;
// look for direct .ciso file
strcpy( strrchr( fname, '.' ), ".ciso" ); // replace .iso with .ciso
if ( stat( fname, &st ) == 0 ) return 1;
// direct file not found, check subdirs
*fname = 0;
DIR_ITER *dir_iter;
char path[MAX_FAT_PATH];
char name[MAX_FAT_PATH];
strcpy( path, wbfs_fs_drive );
strcat( path, wbfs_fat_dir );
dir_iter = diropen( path );
//printf("dir: %s %p\n", path, dir); Wpad_WaitButtons();
if ( !dir_iter )
{
return 0;
}
while ( dirnext( dir_iter, name, &st ) == 0 )
{
//dbg_printf("name:%s\n", name);
if ( name[0] == '.' ) continue;
int n = strlen( name );
if ( n < 8 ) continue;
if ( S_ISDIR( st.st_mode ) )
{
if ( name[6] == '_' )
{
// GAMEID_TITLE
if ( strncmp( name, ( char* )id, 6 ) != 0 ) goto try_alter;
}
else
{
try_alter:
// TITLE [GAMEID]
if ( name[n-8] != '[' || name[n-1] != ']' ) continue;
if ( strncmp( &name[n-7], ( char* )id, 6 ) != 0 ) continue;
}
// look for .wbfs file
snprintf( fname, len, "%s/%s/%.6s.wbfs", path, name, id );
if ( stat( fname, &st ) == 0 ) break;
// look for .iso file
snprintf( fname, len, "%s/%s/%.6s.iso", path, name, id );
if ( stat( fname, &st ) == 0 ) break;
// look for .ciso file
snprintf( fname, len, "%s/%s/%.6s.ciso", path, name, id );
}
else
{
// TITLE [GAMEID].wbfs
char fn_title[TITLE_LEN];
u8 fn_id[8];
char *p = strrchr( name, '.' );
if ( !p ) continue;
if ( ( strcasecmp( p, ".wbfs" ) != 0 )
&& ( strcasecmp( p, ".iso" ) != 0 )
&& ( strcasecmp( p, ".ciso" ) != 0 ) ) continue;
int n = p - name; // length withouth .wbfs
if ( !CheckLayoutB( name, n, fn_id, fn_title ) ) continue;
if ( strncmp( ( char* )fn_id, ( char* )id, 6 ) != 0 ) continue;
snprintf( fname, len, "%s/%s", path, name );
}
if ( stat( fname, &st ) == 0 ) break;
*fname = 0;
}
dirclose( dir_iter );
if ( *fname )
{
// found
//printf("found:%s\n", fname);
return 2;
}
// not found
return 0;
}
wbfs_t* Wbfs_Fat::OpenPart( char *fname )
{
wbfs_t *part = NULL;
int ret;
// wbfs 'partition' file
ret = split_open( &split, fname );
if ( ret ) return NULL;
part = wbfs_open_partition(
split_read_sector,
nop_rw_sector, //readonly //split_write_sector,
&split, fat_sector_size, split.total_sec, 0, 0 );
if ( !part )
{
split_close( &split );
}
return part;
}
void Wbfs_Fat::ClosePart( wbfs_t* part )
{
if ( !part ) return;
split_info_t *s = ( split_info_t* )part->callback_data;
wbfs_close( part );
if ( s ) split_close( s );
}
void Wbfs_Fat::Filename( u8 *id, char *fname, int len, char *path )
{
if ( path == NULL )
{
snprintf( fname, len, "%s%s/%.6s.wbfs", wbfs_fs_drive, wbfs_fat_dir, id );
}
else
{
snprintf( fname, len, "%s/%.6s.wbfs", path, id );
}
}
void Wbfs_Fat::GetDir( struct discHdr *header, char *path )
{
strcpy( path, wbfs_fs_drive );
strcat( path, wbfs_fat_dir );
if ( Settings.FatInstallToDir )
{
strcat( path, "/" );
int layout = 0;
if ( Settings.FatInstallToDir == 2 ) layout = 1;
mk_gameid_title( header, path + strlen( path ), 0, layout );
}
}
wbfs_t* Wbfs_Fat::CreatePart( u8 *id, char *path )
{
char fname[MAX_FAT_PATH];
wbfs_t *part = NULL;
u64 size = ( u64 )143432 * 2 * 0x8000ULL;
u32 n_sector = size / 512;
int ret;
//printf("CREATE PART %s %lld %d\n", id, size, n_sector);
snprintf( fname, sizeof( fname ), "%s%s", wbfs_fs_drive, wbfs_fat_dir );
mkdir( fname, 0777 ); // base usb:/wbfs
mkdir( path, 0777 ); // game subdir
Filename( id, fname, sizeof( fname ), path );
printf( "Writing to %s\n", fname );
ret = split_create( &split, fname, OPT_split_size, size, true );
if ( ret ) return NULL;
// force create first file
u32 scnt = 0;
int fd = split_get_file( &split, 0, &scnt, 0 );
if ( fd < 0 )
{
printf( "ERROR creating file\n" );
sleep( 2 );
split_close( &split );
return NULL;
}
part = wbfs_open_partition(
split_read_sector,
split_write_sector,
&split, fat_sector_size, n_sector, 0, 1 );
if ( !part )
{
split_close( &split );
}
return part;
}
void Wbfs_Fat::mk_title_txt( struct discHdr *header, char *path )
{
char fname[MAX_FAT_PATH];
FILE *f;
strcpy( fname, path );
strcat( fname, "/" );
mk_gameid_title( header, fname + strlen( fname ), 1, 0 );
strcat( fname, ".txt" );
f = fopen( fname, "wb" );
if ( !f ) return;
fprintf( f, "%.6s = %.64s\n", header->id, get_title( header ) );
fclose( f );
printf( "Info file: %s\n", fname );
}
void Wbfs_Fat::mk_gameid_title( struct discHdr *header, char *name, int re_space, int layout )
{
int i, len;
char title[65];
char id[8];
memcpy( name, header->id, 6 );
name[6] = 0;
strncpy( title, get_title( header ), sizeof( title ) );
title_filename( title );
if ( layout == 0 )
{
sprintf( name, "%s_%s", id, title );
}
else
{
sprintf( name, "%s [%s]", title, id );
}
// replace space with '_'
if ( re_space )
{
len = strlen( name );
for ( i = 0; i < len; i++ )
{
if ( name[i] == ' ' ) name[i] = '_';
}
}
}
void Wbfs_Fat::title_filename( char *title )
{
int i, len;
// trim leading space
len = strlen( title );
while ( *title == ' ' )
{
memmove( title, title + 1, len );
len--;
}
// trim trailing space - not allowed on windows directories
while ( len && title[len-1] == ' ' )
{
title[len-1] = 0;
len--;
}
// replace silly chars with '_'
for ( i = 0; i < len; i++ )
{
if ( strchr( invalid_path, title[i] ) || iscntrl( ( int ) title[i] ) )
{
title[i] = '_';
}
}
}
bool Wbfs_Fat::is_gameid( char *id )
{
int i;
for ( i = 0; i < 6; i++ )
{
if ( !isalnum( ( u32 ) id[i] ) ) return false;
}
return true;
}
int Wbfs_Fat::GetFragList( u8 *id )
{
char fname[1024];
char fname1[1024];
struct stat st;
FragList *fs = NULL;
FragList *fa = NULL;
FragList *fw = NULL;
int ret;
int i;
int is_wbfs = 0;
int ret_val = -1;
ret = FindFilename( id, fname, sizeof( fname ) );
if ( !ret ) return -1;
if ( strcasecmp( strrchr( fname, '.' ), ".wbfs" ) == 0 )
{
is_wbfs = 1;
}
fs = ( FragList * ) malloc( sizeof( FragList ) );
fa = ( FragList * ) malloc( sizeof( FragList ) );
fw = ( FragList * ) malloc( sizeof( FragList ) );
frag_init( fa, MAX_FRAG );
for ( i = 0; i < 10; i++ )
{
frag_init( fs, MAX_FRAG );
if ( i > 0 )
{
fname[strlen( fname )-1] = '0' + i;
if ( stat( fname, &st ) == -1 ) break;
}
strcpy( fname1, fname );
if ( ( ret = GetFragList( ( char * ) & fname, &_frag_append, fs ) ) )
{
ret_val = ret;
goto out;
}
frag_concat( fa, fs );
}
frag_list = ( FragList * ) malloc( sizeof( FragList ) );
frag_init( frag_list, MAX_FRAG );
if ( is_wbfs )
{
// if wbfs file format, remap.
//printf("=====\n");
wbfs_disc_t *d = OpenDisc( id );
if ( !d ) goto out;
frag_init( fw, MAX_FRAG );
ret = wbfs_get_fragments( d, &_frag_append, fw );
if ( ret ) goto out;
CloseDisc( d );
// DEBUG:
//frag_list->num = MAX_FRAG-10; // stress test
ret = frag_remap( frag_list, fw, fa );
if ( ret ) goto out;
}
else
{
// .iso does not need remap just copy
//printf("fa:\n");
memcpy( frag_list, fa, sizeof( FragList ) );
}
ret_val = 0;
out:
if ( ret_val )
{
// error
SAFE_FREE( frag_list );
}
SAFE_FREE( fs );
SAFE_FREE( fa );
SAFE_FREE( fw );
return ret_val;
}
int Wbfs_Fat::GetFragList( char *filename, _frag_append_t append_fragment, FragList *fs )
{
return _FAT_get_fragments( filename, append_fragment, fs );
}
bool Wbfs_Fat::ShowFreeSpace( void )
{
return false;
}