Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
73 changes: 73 additions & 0 deletions libraries/libwhb/include/whb/hfio.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
#pragma once
#include <wut.h>

/**
* \defgroup whb_hfio Host I/O access
* \ingroup whb
* @{
*/

#ifdef __cplusplus
extern "C" {
#endif

typedef enum WHBWellKnownHostDirectory
{
//! A way to quickly reference the emulated MLC directory on a attached host
//! pc.
//!
//! You should prefer to use this for compatability (as it will be the same
//! across systems, even with separate paths), and it will usually be fewer
//! characters meaning the actual path can be used by more of the important
//! stuff.
WHB_MLC_HOST_DIRECTORY = 0,
//! A way to quickly reference the emulated SLC directory on a attached host
//! pc.
//!
//! You should prefer to use this for compatability (as it will be the same
//! across systems, even with separate paths), and it will usually be fewer
//! characters meaning the actual path can be used by more of the important
//! stuff.
WHB_SLC_HOST_DIRECTORY = 1,
//! A way to quickly reference the emulated directory of the 'optical disc'
//! on a attached host pc.
//!
//! You should prefer to use this for compatability (as it will be the same
//! across systems, even with separate paths), and it will usually be fewer
//! characters meaning the actual path can be used by more of the important
//! stuff.
WHB_DISC_HOST_DIRECTORY = 2,
//! A way to quickly reference the emulated directory of the current titles
//! save directory.
//!
//! You should prefer to use this for compatability (as it will be the same
//! across systems, even with separate paths), and it will usually be fewer
//! characters meaning the actual path can be used by more of the important
//! stuff.
WHB_SAVE_HOST_DIRECTORY = 3,
//! A way to quickly reference an attached network drive of the host pc.
//!
//! You should prefer to use this for compatability (as it will be the same
//! across systems, even with separate paths), and it will usually be fewer
//! characters meaning the actual path can be used by more of the important
//! stuff.
WHB_NETWORK_DRIVE_HOST_DIRECTORY = 4,
} WHBWellKnownHostDirectory;

BOOL
WHBMountHostFileIO();

char *
WHBGetHostFileIOMountPath();

char *
WHBPathForWellKnownHostDirectory(WHBWellKnownHostDirectory directory);

BOOL
WHBUnmountHostFileIO();

#ifdef __cplusplus
}
#endif

/** @} */
122 changes: 122 additions & 0 deletions libraries/libwhb/src/hfio.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
#include <coreinit/filesystem.h>
#include <coreinit/memdefaultheap.h>
#include <string.h>
#include <whb/hfio.h>
#include <whb/log.h>


static BOOL
sHFIOMounted = FALSE;

static char
sHFIOMountPath[128] = {0};

static FSClient
sHFIOClient;

BOOL
WHBMountHostFileIO()
{
FSCmdBlock cmd;
FSMountSource mountSource;
FSStatus result;

if (sHFIOMounted) {
return TRUE;
}

FSInit();

result = FSAddClient(&sHFIOClient, FS_ERROR_FLAG_ALL);
if (result != FS_STATUS_OK) {
WHBLogPrintf("%s: FSAddClient error %d", __FUNCTION__, result);
return FALSE;
}

FSInitCmdBlock(&cmd);
result = FSGetMountSource(&sHFIOClient, &cmd, FS_MOUNT_SOURCE_HFIO, &mountSource, FS_ERROR_FLAG_ALL);
if (result < 0) {
WHBLogPrintf("%s: FSGetMountSource error %d", __FUNCTION__, result);
goto fail;
}

result = FSMount(&sHFIOClient, &cmd, &mountSource, sHFIOMountPath, sizeof(sHFIOMountPath), FS_ERROR_FLAG_ALL);
if (result < 0) {
WHBLogPrintf("%s: FSMount error %d", __FUNCTION__, result);
goto fail;
}

sHFIOMounted = TRUE;
return TRUE;

fail:
FSDelClient(&sHFIOClient, FS_ERROR_FLAG_ALL);
return FALSE;
}

char *
WHBGetHostFileIOMountPath()
{
return sHFIOMountPath;
}

char *
WHBPathForWellKnownHostDirectory(WHBWellKnownHostDirectory directory)
{
// The host path is 128 bytes, and the maximum we can append is 15 bytes, for a final size of 143.
char *finalPath = (char *)MEMAllocFromDefaultHeap(143);
if (finalPath == NULL) {
return NULL;
}

// Ensure we get a NULL terminator, mimic calloc.
memset(finalPath, 0, 143);
strcat(finalPath, sHFIOMountPath);
strcat(finalPath, "/");
switch (directory) {
case WHB_MLC_HOST_DIRECTORY:
strcat(finalPath, "%MLC_EMU_DIR");
break;
case WHB_SLC_HOST_DIRECTORY:
strcat(finalPath, "%SLC_EMU_DIR");
break;
case WHB_DISC_HOST_DIRECTORY:
strcat(finalPath, "%DISC_EMU_DIR");
break;
case WHB_SAVE_HOST_DIRECTORY:
strcat(finalPath, "%SAVE_EMU_DIR");
break;
case WHB_NETWORK_DRIVE_HOST_DIRECTORY:
strcat(finalPath, "%NETWORK");
break;
}
return finalPath;
}

BOOL
WHBUnmountHostFileIO()
{
FSCmdBlock cmd;
FSStatus result;

if (!sHFIOMounted) {
return TRUE;
}

FSInitCmdBlock(&cmd);

result = FSUnmount(&sHFIOClient, &cmd, sHFIOMountPath, FS_ERROR_FLAG_ALL);
if (result < 0) {
WHBLogPrintf("%s: FSUnmount error %d", __FUNCTION__, result);
return FALSE;
}

result = FSDelClient(&sHFIOClient, FS_ERROR_FLAG_ALL);
if (result < 0) {
WHBLogPrintf("%s: FSDelClient error %d", __FUNCTION__, result);
return FALSE;
}

sHFIOMounted = FALSE;
return TRUE;
}