add methods to access file based emummc

This commit is contained in:
Christoph Baumann
2025-05-07 16:42:36 +02:00
parent 39b74dd50d
commit 942e7defe3
2 changed files with 240 additions and 0 deletions

226
bdk/storage/emummc.c Normal file
View File

@@ -0,0 +1,226 @@
#include "emummc.h"
#include <string.h>
#include <stdlib.h>
#include <libs/fatfs/ff.h>
#include <gfx_utils.h>
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;
}

14
bdk/storage/emummc.h Normal file
View File

@@ -0,0 +1,14 @@
#ifndef EMUMMC_H
#define EMUMMC_H
#include <bdk.h>
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