static ssize_t FSDrvRead(struct _reent* r, int fd, char* ptr, size_t len) { FSFileHandle* handle = (FSFileHandle*) fd; void* buf = ptr; if(((u32) ptr & (FS_IO_BUFFER_ALIGN - 1)) != 0) { buf = memalign(FS_IO_BUFFER_ALIGN, len); if(buf == NULL) { r->_errno = ENOMEM; return -1; } } FSStatus err = FSReadFile(fsClient, fsCmdBlock, buf, 1, len, *handle, FS_IO_FLAG_NONE, FS_RET_ALL_ERROR); if(((u32) ptr & (FS_IO_BUFFER_ALIGN - 1)) != 0) { if(err >= FS_STATUS_OK) { memcpy(ptr, buf, (size_t) err); } free(buf); } if(err < FS_STATUS_OK) { FSDrvReportError(r); return -1; } return err; }
static ssize_t sd_fat_read_r (struct _reent *r, int fd, char *ptr, size_t len) { sd_fat_file_state_t *file = (sd_fat_file_state_t *)fd; if(!file->dev) { r->_errno = ENODEV; return 0; } if(!file->read) { r->_errno = EACCES; return 0; } OSLockMutex(file->dev->pMutex); size_t len_aligned = FS_ALIGN(len); if(len_aligned > 0x4000) len_aligned = 0x4000; unsigned char *tmpBuf = (unsigned char *)memalign(FS_ALIGNMENT, len_aligned); if(!tmpBuf) { r->_errno = ENOMEM; OSUnlockMutex(file->dev->pMutex); return 0; } size_t done = 0; while(done < len) { size_t read_size = (len_aligned < (len - done)) ? len_aligned : (len - done); int result = FSReadFile(file->dev->pClient, file->dev->pCmd, tmpBuf, 0x01, read_size, file->fd, 0, -1); if(result < 0) { r->_errno = result; done = 0; break; } else if(result == 0) { //! TODO: error on read_size > 0 break; } else { memcpy(ptr + done, tmpBuf, read_size); done += result; file->pos += result; } } free(tmpBuf); OSUnlockMutex(file->dev->pMutex); return done; }
FSStatus FSReadFileAsync(FSClient *client, FSCmdBlock *block, uint8_t *buffer, uint32_t size, uint32_t count, FSFileHandle handle, uint32_t unk1, uint32_t flags, FSAsyncData *asyncData) { assert(asyncData->callback); auto result = FSReadFile(client, block, buffer, size, count, handle, unk1, flags); FSAsyncCallback cb = static_cast<uint32_t>(asyncData->callback); cb(client, block, result, asyncData->param); return result; }
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; }