diff --git a/bdk/storage/emummc.c b/bdk/storage/emummc.c new file mode 100644 index 00000000..879b5a02 --- /dev/null +++ b/bdk/storage/emummc.c @@ -0,0 +1,226 @@ +#include "emummc.h" +#include +#include +#include +#include + +static FIL active_file; +// -0xff: none, -1: boot 0, -2: boot1, 0+: gpp +static s32 active_file_idx; +static char file_based_base_path[0x80]; +static u32 file_part_sz_sct; +static u32 active_part; +static u32 file_based_base_path_len; + +static int _emummc_storage_file_based_read_write_single(u32 sector, u32 num_sectors, void *buf, bool is_write){ + #if FF_FS_READONLY == 1 + if(is_write){ + return 0; + } + #endif + + int res = f_lseek(&active_file, (u64)sector << 9); + if(res != FR_OK){ + return res; + } + + if(is_write){ + res = f_write(&active_file, buf, (u64)num_sectors << 9, NULL); + }else{ + res = f_read(&active_file, buf, (u64)num_sectors << 9, NULL); + } + + if(res != FR_OK){ + return res; + } + + return FR_OK; +} + +static int _emummc_storage_file_based_change_file(const char *name, s32 idx){ + int res; + + if(active_file_idx == idx){ + return FR_OK; + } + + if(active_file_idx != -0xff){ + f_close(&active_file); + active_file_idx = -0xff; + } + + strcpy(file_based_base_path + file_based_base_path_len, name); + + gfx_printf("new f %s \n", file_based_base_path); + + #if FF_FS_READONLY == 1 + res = f_open(&active_file, file_based_base_path, FA_READ); + #else + res = f_open(&active_file, file_based_base_path, FA_READ | FA_WRITE); + #endif + + if(res != FR_OK){ + return res; + } + active_file_idx = idx; + + return FR_OK; +} + +static int _emummc_storage_file_based_read_write(u32 sector, u32 num_sectors, void *buf, bool is_write){ + #if FF_FS_READONLY == 1 + if(is_write){ + return 0; + } + #endif + + if(file_part_sz_sct == 0){ + return 0; + } + + int res; + + if(active_part == 1){ + // boot0 + res = _emummc_storage_file_based_change_file("BOOT0", -1); + if(res != FR_OK){ + return 0; + } + return _emummc_storage_file_based_read_write_single(sector, num_sectors, buf, is_write) == FR_OK; + }else if(active_part == 2){ + // boot1 + res = _emummc_storage_file_based_change_file("BOOT1", -2); + if(res != FR_OK){ + return 0; + } + return _emummc_storage_file_based_read_write_single(sector, num_sectors, buf, is_write) == FR_OK; + }else if(active_part == 0){ + // GPP + if(file_part_sz_sct == 0){ + return 0; + } + + gfx_printf("emu w %x %x \n", sector, num_sectors); + + u32 scts_left = num_sectors; + u32 cur_sct = sector; + while(scts_left){ + // offset within file + u32 offset = cur_sct % file_part_sz_sct; + // read up to start of next file or sectors left, whatever is less + u32 sct_cnt = file_part_sz_sct - offset; + sct_cnt = MIN(sct_cnt, scts_left); + + u32 file_idx = cur_sct / file_part_sz_sct; + + gfx_printf("idx %d cnt %x off %x \n", file_idx, sct_cnt, offset); + if((s32)file_idx != active_file_idx){ + gfx_printf("active idx %d \n", active_file_idx); + char name[3] = ""; + if(file_idx < 10){ + strcpy(name, "0"); + } + itoa(file_idx, name + strlen(name), 10); + + gfx_printf("new name %s \n", name); + + res = _emummc_storage_file_based_change_file(name, file_idx); + if(res != FR_OK){ + gfx_printf("fail change file \n"); + return 0; + } + } + + res = _emummc_storage_file_based_read_write_single(offset, sct_cnt, buf + ((u64)(num_sectors - scts_left) << 9), is_write); + + if(res != FR_OK){ + gfx_printf("rw single fail %d \n", res); + return 0; + } + + cur_sct += sct_cnt; + scts_left -= sct_cnt; + } + return 1; + } + return 0; +} + +int emummc_storage_file_base_set_partition(u32 partition){ + active_part = partition; + return 1; +} + +int emummc_storage_file_based_init(const char *path){ + gfx_printf("emu init %s \n", path); + strcpy(file_based_base_path, path); + file_based_base_path_len = strlen(file_based_base_path); + strcat(file_based_base_path + file_based_base_path_len, "00"); + + active_part = 0; + + FILINFO fi; + if(f_stat(file_based_base_path, &fi) != FR_OK){ + gfx_printf("emu init fstat failed %s \n", path); + return 0; + } + + file_part_sz_sct = 0; + if(fi.fsize){ + file_part_sz_sct = fi.fsize >> 9; + } + + active_file_idx = -0xff; + + return 1; +} + +void emummc_storage_file_based_end(){ + if(active_file_idx != -0xff){ + f_close(&active_file); + } + active_file_idx = -0xff; + file_based_base_path[0] = '\0'; + file_part_sz_sct = 0; +} + +#if FF_FS_READONLY == 0 +int emummc_storage_file_based_write(u32 sector, u32 num_sectors, void *buf){ + return _emummc_storage_file_based_read_write(sector, num_sectors, buf, true); +} +#endif + +int emummc_storage_file_based_read(u32 sector, u32 num_sectors, void *buf){ + return _emummc_storage_file_based_read_write(sector, num_sectors, buf, false); +} + +u32 emummc_storage_file_based_get_total_gpp_size(const char *path){ + u32 path_len = strlen(path); + u32 total_size_sct = 0; + char file_path[0x80]; + u32 cur_idx = 0; + int res; + + strcpy(file_path, path); + strcpy(file_path + path_len, "00"); + + FILINFO fi; + res = f_stat(file_path, &fi); + + while(res == FR_OK){ + cur_idx++; + total_size_sct += fi.fsize >> 9; + + char name[3] = "0"; + if(cur_idx >= 10){ + name[0] = '\0'; + } + itoa(cur_idx, name + strlen(name), 10); + + strcpy(file_path + path_len, name); + + res = f_stat(file_path, &fi); + } + + return total_size_sct; +} \ No newline at end of file diff --git a/bdk/storage/emummc.h b/bdk/storage/emummc.h new file mode 100644 index 00000000..d25abc79 --- /dev/null +++ b/bdk/storage/emummc.h @@ -0,0 +1,14 @@ +#ifndef EMUMMC_H +#define EMUMMC_H + +#include + +int emummc_storage_file_base_set_partition(u32 partition); +int emummc_storage_file_based_init(const char *path); +void emummc_storage_file_based_end(); +int emummc_storage_file_based_write(u32 sector, u32 num_sectors, void *buf); +int emummc_storage_file_based_read(u32 sector, u32 num_sectors, void *buf); +u32 emummc_storage_file_based_get_total_size(const char *path); +sdmmc_storage_t *emummc_get_storage(); + +#endif \ No newline at end of file