int mount_sd_fat(const char *path) { int result = -1; // get command and client void* pClient = malloc(sizeof(FSClient)); void* pCmd = malloc(sizeof(FSCmdBlock)); if(!pClient || !pCmd) { // just in case free if not 0 if(pClient) free(pClient); if(pCmd) free(pCmd); return -2; } FSInit(); FSInitCmdBlock(pCmd); FSAddClient(pClient, -1); char *mountPath = NULL; if(MountFS(pClient, pCmd, &mountPath) == 0) { result = sd_fat_add_device(path, mountPath, pClient, pCmd); free(mountPath); } return result; }
int __wut_fs_rmdir(struct _reent *r, const char *name) { FSStatus rc; if (name == NULL) { return -1; } char *path_fix = __wut_fs_fixpath(r, name); if (!path_fix) { r->_errno = ENOMEM; return -1; } // Set up command block FSCmdBlock fsCmd; FSInitCmdBlock(&fsCmd); rc = FSRemove(__wut_devoptab_fs_client, &fsCmd, path_fix, -1); free(path_fix); if (rc >= 0) { return 0; } r->_errno = __wut_fs_translate_error(rc); return -1; }
DECL(int, FSInit, void) { if ((int)bss_ptr == 0x0a000000) { // allocate memory for our stuff void *mem_ptr = memalign(sizeof(struct bss_t), 0x40); if(!mem_ptr) return real_FSInit(); // copy pointer bss_ptr = mem_ptr; memset(bss_ptr, 0, sizeof(struct bss_t)); // setup exceptions setup_os_exceptions(); // create game mount path prefix __os_snprintf(bss.mount_base, sizeof(bss.mount_base), "%s%s/%s%s", CAFE_OS_SD_PATH, SD_GAMES_PATH, GAME_DIR_NAME, CONTENT_PATH); // create game save path prefix __os_snprintf(bss.save_base, sizeof(bss.save_base), "%s%s/%s", CAFE_OS_SD_PATH, SD_SAVES_PATH, GAME_DIR_NAME); logger_connect(&bss.global_sock); // Call real FSInit int result = real_FSInit(); // Mount sdcard FSClient *pClient = (FSClient*) MEMAllocFromDefaultHeap(sizeof(FSClient)); if (!pClient) return 0; FSCmdBlock *pCmd = (FSCmdBlock*) MEMAllocFromDefaultHeap(sizeof(FSCmdBlock)); if (!pCmd) { MEMFreeToDefaultHeap(pClient); return 0; } FSInitCmdBlock(pCmd); FSAddClientEx(pClient, 0, FS_RET_NO_ERROR); fs_mount_sd(bss.global_sock, pClient, pCmd); FSDelClient(pClient); MEMFreeToDefaultHeap(pCmd); MEMFreeToDefaultHeap(pClient); return result; } return real_FSInit(); }
int __wut_fs_rename(struct _reent *r, const char *oldName, const char *newName) { FSStatus rc; if (oldName == NULL) { return -1; } if (newName == NULL) { return -1; } char *path_old = __wut_fs_fixpath(r, oldName); if (!path_old) { r->_errno = ENOMEM; return -1; } char *path_new = __wut_fs_fixpath(r, newName); if (!path_new) { r->_errno = ENOMEM; return -1; } // Set up command block FSCmdBlock fsCmd; FSInitCmdBlock(&fsCmd); rc = FSRename(__wut_devoptab_fs_client, &fsCmd, path_old, path_new, -1); free(path_old); free(path_new); if (rc >= 0) { return 0; } r->_errno = __wut_fs_translate_error(rc); return -1; }
void _start() { /* Load a good stack */ asm( "lis %r1, 0x1ab5 ;" "ori %r1, %r1, 0xd138 ;" ); /* Get a handle to coreinit.rpl */ uint32_t coreinit_h; OSDynLoad_Acquire("coreinit.rpl", &coreinit_h); /* Memory allocation and FS functions */ void* (*OSAllocFromSystem)(uint32_t size, int align); int (*FSInit)(); int (*FSAddClient)(void *client, int unk1); int (*FSInitCmdBlock)(void *cmd); int (*FSOpenDir)(void *client, void *cmd, char *path, uint32_t *dir_handle, int unk1); int (*FSReadDir)(void *client, void *cmd, uint32_t dir_handle, void *buffer, int unk1); int (*FSGetMountSource)(void *client, void *cmd, int type, mount_source *source, int unk1); int (*FSMount)(void *client, void *cmd, mount_source *source, char *mountpath, uint32_t pathlength, int unk1); int (*FSOpenFile)(void *client, void *cmd, char *filepath, char *amode, uint32_t *file_handle, int unk1); int (*FSReadFile)(void *client, void *cmd, void *buffer, uint32_t size, uint32_t length, uint32_t file_handle, int unk1, int unk2); OSDynLoad_FindExport(coreinit_h, 0, "OSAllocFromSystem", &OSAllocFromSystem); OSDynLoad_FindExport(coreinit_h, 0, "FSInit", &FSInit); OSDynLoad_FindExport(coreinit_h, 0, "FSAddClient", &FSAddClient); OSDynLoad_FindExport(coreinit_h, 0, "FSInitCmdBlock", &FSInitCmdBlock); OSDynLoad_FindExport(coreinit_h, 0, "FSOpenDir", &FSOpenDir); OSDynLoad_FindExport(coreinit_h, 0, "FSReadDir", &FSReadDir); OSDynLoad_FindExport(coreinit_h, 0, "FSGetMountSource", &FSGetMountSource); OSDynLoad_FindExport(coreinit_h, 0, "FSMount", &FSMount); OSDynLoad_FindExport(coreinit_h, 0, "FSOpenFile", &FSOpenFile); OSDynLoad_FindExport(coreinit_h, 0, "FSReadFile", &FSReadFile); FSInit(); /* Set up the client and command blocks */ void *client = OSAllocFromSystem(0x1700, 0x20); void *cmd = OSAllocFromSystem(0xA80, 0x20); if (!(client && cmd)) OSFatal("Failed to allocate client and command block"); FSAddClient(client, 0); FSInitCmdBlock(cmd); // todo: check permissions and throw exception if no mounting permissions available // OSLockMutex - Probably not. It's a single thread, nothing else can access this, Cross-F does this here mount_source m_source; // allocate mount source int ms_result = FSGetMountSource(client, cmd, 0, &m_source, 0); // type 0 = external device if(ms_result != 0) { char buf[256]; __os_snprintf(buf, 256, "FSGetMountSource returned error code %d", ms_result); OSFatal(buf); } char mountPath[128]; // usually /vol/external01 int m_result = FSMount(client, cmd, &m_source, mountPath, sizeof(mountPath), -1); if(m_result != 0) { char buf[256]; __os_snprintf(buf, 256, "FSMount returned error code %d", m_result); OSFatal(buf); } // OSUnlockMutex char defaultMountPath[] = "/vol/external01"; if(!strcmp(mountPath, defaultMountPath)) { char buf[256]; __os_snprintf(buf, 256, "FSMount returned nonstandard mount path: %s", mountPath); OSFatal(buf); } uint32_t file_handle; int open_result = FSOpenFile(client, cmd, "/vol/external01/SMASHD.txt", "r", &file_handle, 0); if(open_result != 0) { char buf[256]; __os_snprintf(buf, 256, "FSOpenFile returned error code %d", open_result); OSFatal(buf); } uint32_t *file_buffer = OSAllocFromSystem(0x200, 0x20); int read_result = FSReadFile(client, cmd, file_buffer, 1, 25, file_handle, 0, -1); // todo: is size correct? one char one byte; read whole file, not just a few bytes if(read_result != 0) { char buf[256]; __os_snprintf(buf, 256, "FSReadFile returned error code %d", read_result); OSFatal(buf); } char *message = (char*)&file_buffer[25]; OSFatal(message); }
/* ***************************************************************************** * Dynamic RPL loading to memory * ****************************************************************************/ static int LoadRPLToMemory(s_rpx_rpl *rpl_entry) { if ((int)bss_ptr != 0x0a000000) { char buffer[200]; __os_snprintf(buffer, sizeof(buffer), "CheckAndLoadRPL(%s) found and loading", rpl_entry->name); log_string(bss.global_sock, buffer, BYTE_LOG_STR); } // initialize FS FSInit(); FSClient *pClient = (FSClient*) MEMAllocFromDefaultHeap(sizeof(FSClient)); if (!pClient) return 0; FSCmdBlock *pCmd = (FSCmdBlock*) MEMAllocFromDefaultHeap(sizeof(FSCmdBlock)); if (!pCmd) { MEMFreeToDefaultHeap(pClient); return 0; } // calculate path length for SD access of RPL int path_len = strlen(CAFE_OS_SD_PATH) + strlen(SD_GAMES_PATH) + strlen(GAME_DIR_NAME) + strlen(RPX_RPL_PATH) + strlen(rpl_entry->name) + 3; char *path_rpl = MEMAllocFromDefaultHeap(path_len); if(!path_rpl) { MEMFreeToDefaultHeap(pCmd); MEMFreeToDefaultHeap(pClient); return 0; } // create path __os_snprintf(path_rpl, path_len, "%s%s/%s%s/%s", CAFE_OS_SD_PATH, SD_GAMES_PATH, GAME_DIR_NAME, RPX_RPL_PATH, rpl_entry->name); // malloc mem for read file unsigned char* dataBuf = (unsigned char*)MEMAllocFromDefaultHeapEx(0x1000, 0x40); if(!dataBuf) { MEMFreeToDefaultHeap(pCmd); MEMFreeToDefaultHeap(pClient); MEMFreeToDefaultHeap(path_rpl); return 0; } // do more initial FS stuff FSInitCmdBlock(pCmd); FSAddClientEx(pClient, 0, FS_RET_NO_ERROR); // set RPL size to 0 to avoid wrong RPL being loaded when opening file fails rpl_entry->size = 0; rpl_entry->offset = 0; int fd = 0; if (real_FSOpenFile(pClient, pCmd, path_rpl, "r", &fd, FS_RET_ALL_ERROR) == FS_STATUS_OK) { int ret; int rpl_size = 0; // Get current memory area s_mem_area* mem_area = (s_mem_area*)(MEM_AREA_ARRAY); int mem_area_addr_start = mem_area->address; int mem_area_addr_end = mem_area->address + mem_area->size; int mem_area_offset = 0; // Copy rpl in memory while ((ret = FSReadFile(pClient, pCmd, dataBuf, 0x1, 0x1000, fd, 0, FS_RET_ALL_ERROR)) > 0) { // Copy in memory and save offset for (int j = 0; j < ret; j++) { if ((mem_area_addr_start + mem_area_offset) >= mem_area_addr_end) { // Set next memory area mem_area = mem_area->next; mem_area_addr_start = mem_area->address; mem_area_addr_end = mem_area->address + mem_area->size; mem_area_offset = 0; } *(volatile unsigned char*)(mem_area_addr_start + mem_area_offset) = dataBuf[j]; mem_area_offset += 1; } rpl_size += ret; } // Fill rpl entry rpl_entry->area = (s_mem_area*)(MEM_AREA_ARRAY); rpl_entry->offset = 0; rpl_entry->size = rpl_size; // flush memory // DCFlushRange((void*)rpl_entry, sizeof(s_rpx_rpl)); // DCFlushRange((void*)rpl_entry->address, rpl_entry->size); if ((int)bss_ptr != 0x0a000000) { char buffer[200]; __os_snprintf(buffer, sizeof(buffer), "CheckAndLoadRPL(%s) file loaded 0x%08X %i", rpl_entry->name, rpl_entry->area->address, rpl_entry->size); log_string(bss.global_sock, buffer, BYTE_LOG_STR); } FSCloseFile(pClient, pCmd, fd, FS_RET_NO_ERROR); } FSDelClient(pClient); MEMFreeToDefaultHeap(dataBuf); MEMFreeToDefaultHeap(pCmd); MEMFreeToDefaultHeap(pClient); MEMFreeToDefaultHeap(path_rpl); return 1; }