mirror of
https://github.com/Fledge68/WiiFlow_Lite.git
synced 2024-11-01 09:05:06 +01:00
260 lines
5.7 KiB
C
260 lines
5.7 KiB
C
|
|
// WBFS FAT by oggzee
|
|
|
|
#include <stdio.h>
|
|
#include <unistd.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 "wbfs.h"
|
|
#include "wdvd.h"
|
|
#include "splits.h"
|
|
#include "wbfs_ext.h"
|
|
#include "utils.h"
|
|
#include "disc.h"
|
|
|
|
#include "devicemounter/sdhc.h"
|
|
#include "devicemounter/usbstorage.h"
|
|
#include "fileOps/fileOps.h"
|
|
#include "gecko/gecko.hpp"
|
|
#include "libwbfs/libwbfs.h"
|
|
#include "loader/utils.h"
|
|
#include "loader/sys.h"
|
|
#include "gui/fmt.h"
|
|
|
|
#define TITLE_LEN 64
|
|
|
|
char wbfs_fs_drive[16];
|
|
char invalid_path[] = "/\\:|<>?*\"'";
|
|
|
|
split_info_t split;
|
|
|
|
struct statvfs wbfs_ext_vfs;
|
|
|
|
#define STRCOPY(DEST,SRC) strcopy(DEST,SRC,sizeof(DEST))
|
|
char* strcopy(char *dest, const char *src, int size)
|
|
{
|
|
memcpy(dest,src,size);
|
|
dest[size-1] = 0;
|
|
return dest;
|
|
}
|
|
|
|
wbfs_disc_t* WBFS_Ext_OpenDisc(u8 *discid, char *fname)
|
|
{
|
|
bool sd = strstr(fname, "sd") != NULL;
|
|
if (strcasecmp(strrchr(fname,'.'), ".iso") == 0)
|
|
{
|
|
// .iso file
|
|
// create a fake wbfs_disc
|
|
int fd = open(fname, O_RDONLY);
|
|
if (fd == -1) return NULL;
|
|
|
|
wbfs_disc_t *iso_file = malloc(sizeof(wbfs_disc_t));
|
|
memset(iso_file, 0, sizeof(wbfs_disc_t));
|
|
|
|
if (iso_file == NULL)
|
|
return NULL;
|
|
|
|
// mark with a special wbfs_part
|
|
wbfs_iso_file.wbfs_sec_sz = sd ? 512 : USBStorage2_GetSectorSize();
|
|
iso_file->p = &wbfs_iso_file;
|
|
iso_file->header = (void*)fd;
|
|
return iso_file;
|
|
}
|
|
|
|
wbfs_t *part = WBFS_Ext_OpenPart(fname);
|
|
if(!part)
|
|
return NULL;
|
|
|
|
return wbfs_open_disc(part, discid);
|
|
}
|
|
|
|
void WBFS_Ext_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);
|
|
WBFS_Ext_ClosePart(part);
|
|
}
|
|
|
|
s32 WBFS_Ext_DiskSpace(f32 *used, f32 *free)
|
|
{
|
|
*used = 0;
|
|
*free = 0;
|
|
|
|
static s32 wbfs_ext_vfs_have = 0, wbfs_ext_vfs_lba = 0, wbfs_ext_vfs_dev = 0;
|
|
|
|
// statvfs is slow, so cache values
|
|
if (!wbfs_ext_vfs_have || wbfs_ext_vfs_lba != (s32)wbfs_part_lba || wbfs_ext_vfs_dev != wbfsDev )
|
|
{
|
|
if(statvfs(fmt("%s:", wbfs_fs_drive), &wbfs_ext_vfs))
|
|
return 0;
|
|
|
|
wbfs_ext_vfs_have = 1;
|
|
wbfs_ext_vfs_lba = wbfs_part_lba;
|
|
wbfs_ext_vfs_dev = wbfsDev;
|
|
}
|
|
|
|
/* FS size in GB */
|
|
f32 size = (f32)wbfs_ext_vfs.f_frsize * (f32)wbfs_ext_vfs.f_blocks / GB_SIZE;
|
|
*free = (f32)wbfs_ext_vfs.f_frsize * (f32)wbfs_ext_vfs.f_bfree / GB_SIZE;
|
|
*used = size - *free;
|
|
|
|
return 0;
|
|
}
|
|
|
|
wbfs_t* WBFS_Ext_OpenPart(char *fname)
|
|
{
|
|
bool sd = strstr(fname, "sd") != NULL;
|
|
if(split_open(&split, fname) < 0)
|
|
return NULL;
|
|
|
|
wbfs_set_force_mode(1);
|
|
wbfs_t *part = wbfs_open_partition(split_read_sector, 0, //readonly //split_write_sector,
|
|
&split, sd ? 512 : USBStorage2_GetSectorSize(), split.total_sec, 0, 0);
|
|
wbfs_set_force_mode(0);
|
|
|
|
if (!part)
|
|
split_close(&split);
|
|
|
|
return part;
|
|
}
|
|
|
|
void WBFS_Ext_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);
|
|
}
|
|
|
|
s32 WBFS_Ext_RemoveGame(u8 *discid, char *gamepath)
|
|
{
|
|
DIR *dir_iter;
|
|
struct dirent *ent;
|
|
char file[MAX_FAT_PATH];
|
|
char folder[MAX_FAT_PATH];
|
|
STRCOPY(folder, gamepath);// why function STRCOPY and not just strcpy?
|
|
char *p = strrchr(folder, '/');
|
|
if(p) *p = 0;
|
|
|
|
dir_iter = opendir(folder);
|
|
if (!dir_iter) return 0;
|
|
while((ent = readdir(dir_iter)) != NULL)
|
|
{
|
|
if(strstr(ent->d_name, (char*)discid) != NULL)
|
|
{
|
|
strcpy(file, fmt("%s/%s", folder, ent->d_name));
|
|
remove(file);
|
|
}
|
|
}
|
|
closedir(dir_iter);
|
|
if(strlen(folder) > 11)
|
|
unlink(folder);
|
|
return 0;
|
|
}
|
|
|
|
s32 WBFS_Ext_AddGame(progress_callback_t spinner, void *spinner_data)
|
|
{
|
|
struct discHdr header ATTRIBUTE_ALIGN(32);
|
|
|
|
char *illegal = "\"*/:<>?\\|";
|
|
char *cp;
|
|
char *cleantitle;
|
|
|
|
char folder[MAX_FAT_PATH];
|
|
memset(folder, 0, MAX_FAT_PATH);
|
|
|
|
char gamepath[MAX_FAT_PATH];
|
|
memset(gamepath, 0, MAX_FAT_PATH);
|
|
|
|
Disc_ReadHeader(&header);
|
|
asprintf(&cleantitle, header.title);
|
|
for(cp = strpbrk(cleantitle, illegal); cp; cp = strpbrk(cp, illegal))
|
|
*cp = '_';
|
|
memcpy(folder, fmt(wii_games_dir, wbfs_fs_drive), sizeof(folder));
|
|
fsop_MakeFolder(folder);
|
|
memcpy(folder, fmt("%s/%s [%s]", folder, cleantitle, header.id), sizeof(folder));
|
|
fsop_MakeFolder(folder);
|
|
free(cleantitle);
|
|
|
|
memcpy(gamepath, fmt("%s/%s.wbfs", folder, header.id), sizeof(gamepath));
|
|
u64 size = (u64)143432*2*0x8000ULL;
|
|
u32 n_sector = size / 512;
|
|
|
|
if(split_create(&split, gamepath, OPT_split_size, size, true))
|
|
return -1;
|
|
|
|
//force create first file
|
|
u32 scnt = 0;
|
|
if (split_get_file(&split, 0, &scnt, 0) < 0)
|
|
{
|
|
split_close(&split);
|
|
return -1;
|
|
}
|
|
|
|
wbfs_t *part = wbfs_open_partition(split_read_sector, split_write_sector, &split, 512, n_sector, 0, 1);
|
|
if (!part)
|
|
{
|
|
split_close(&split);
|
|
return -1;
|
|
}
|
|
|
|
extern wbfs_t *hdd;
|
|
wbfs_t *old_hdd = hdd;
|
|
hdd = part; // used by spinner
|
|
s32 ret = wbfs_add_disc(part, __WBFS_ReadDVD, NULL, spinner, spinner_data, REMOVE_UPDATE_PARTITION, 0);
|
|
hdd = old_hdd;
|
|
|
|
if(ret == 0) wbfs_trim(part);
|
|
|
|
WBFS_Ext_ClosePart(part);
|
|
|
|
if(ret < 0) WBFS_Ext_RemoveGame(NULL, gamepath);
|
|
|
|
return ret < 0 ? ret : 0;
|
|
}
|
|
|
|
s32 WBFS_Ext_DVD_Size(u64 *comp_size, u64 *real_size)
|
|
{
|
|
s32 ret;
|
|
u32 comp_sec = 0, last_sec = 0;
|
|
|
|
wbfs_t *part = NULL;
|
|
u64 size = (u64)143432*2*0x8000ULL;
|
|
u32 n_sector = size / 512;
|
|
u32 wii_sec_sz;
|
|
|
|
// init a temporary dummy part
|
|
// as a placeholder for wbfs_size_disc
|
|
part = wbfs_open_partition(0, 0, NULL, 512, n_sector, 0, 1);
|
|
if(!part)
|
|
return -1;
|
|
wii_sec_sz = part->wii_sec_sz;
|
|
|
|
/* Add game to device */
|
|
ret = wbfs_size_disc(part, __WBFS_ReadDVD, NULL, REMOVE_UPDATE_PARTITION, &comp_sec, &last_sec);
|
|
wbfs_close(part);
|
|
if(ret < 0)
|
|
return ret;
|
|
|
|
*comp_size = (u64)wii_sec_sz * comp_sec;
|
|
*real_size = (u64)wii_sec_sz * last_sec;
|
|
|
|
return 0;
|
|
}
|