SC64 flashcart code fixes + cleanup

This commit is contained in:
Mateusz Faderewski 2023-08-10 21:20:02 +02:00
parent 420eb8b3ff
commit ac63083089
6 changed files with 101 additions and 90 deletions

View File

@ -18,7 +18,7 @@ SRCS = \
boot/reboot.S \
flashcart/flashcart_utils.c \
flashcart/flashcart.c \
flashcart/sc64/sc64_internal.c \
flashcart/sc64/sc64_ll.c \
flashcart/sc64/sc64.c \
libs/libspng/spng/spng.c \
libs/mini.c/src/mini.c \
@ -44,8 +44,8 @@ SRCS = \
menu/views/fault.c \
menu/views/file_info.c \
menu/views/image_viewer.c \
menu/views/load.c \
menu/views/load_emulator.c \
menu/views/load.c \
menu/views/music_player.c \
menu/views/startup.c \
menu/views/system_info.c \

View File

@ -43,6 +43,11 @@ flashcart_error_t flashcart_init (void) {
bool sd_initialized;
flashcart_error_t error;
#ifndef MENU_RELEASE
// NOTE: Some flashcarts doesn't have USB port, can't throw error here
debug_init_usblog();
#endif
// HACK: Because libcart reads PI config from address 0x10000000 when initializing
// we need to write safe value before running any libcart function.
// Data in SDRAM can be undefined on some flashcarts at this point
@ -77,11 +82,6 @@ flashcart_error_t flashcart_init (void) {
return FLASHCART_ERROR_SD_CARD;
}
#ifndef MENU_RELEASE
// NOTE: Some flashcarts doesn't have USB port, can't throw error here
debug_init_usblog();
#endif
return FLASHCART_OK;
}

View File

@ -9,7 +9,7 @@
#include "utils/utils.h"
#include "../flashcart_utils.h"
#include "sc64_internal.h"
#include "sc64_ll.h"
#include "sc64.h"
@ -21,6 +21,7 @@
#define SUPPORTED_MAJOR_VERSION (2)
#define SUPPORTED_MINOR_VERSION (16)
#define SUPPORTED_REVISION (0)
static flashcart_error_t load_to_flash (FIL *fil, void *address, size_t size, UINT *br, flashcart_progress_callback_t *progress) {
@ -29,19 +30,19 @@ static flashcart_error_t load_to_flash (FIL *fil, void *address, size_t size, UI
*br = 0;
if (sc64_flash_get_erase_block_size(&erase_block_size) != SC64_OK) {
if (sc64_ll_flash_get_erase_block_size(&erase_block_size) != SC64_OK) {
return FLASHCART_ERROR_INT;
}
while (size > 0) {
size_t program_size = MIN(size, erase_block_size);
if (sc64_flash_erase_block(address) != SC64_OK) {
if (sc64_ll_flash_erase_block(address) != SC64_OK) {
return FLASHCART_ERROR_INT;
}
if (f_read(fil, address, program_size, &bp) != FR_OK) {
return FLASHCART_ERROR_LOAD;
}
if (sc64_flash_wait_busy() != SC64_OK) {
if (sc64_ll_flash_wait_busy() != SC64_OK) {
return FLASHCART_ERROR_INT;
}
if (progress) {
@ -60,7 +61,7 @@ static flashcart_error_t sc64_init (void) {
uint16_t minor;
uint32_t revision;
if (sc64_get_version(&major, &minor, &revision) != SC64_OK) {
if (sc64_ll_get_version(&major, &minor, &revision) != SC64_OK) {
return FLASHCART_ERROR_OUTDATED;
}
if (major != SUPPORTED_MAJOR_VERSION) {
@ -68,37 +69,39 @@ static flashcart_error_t sc64_init (void) {
}
if (minor < SUPPORTED_MINOR_VERSION) {
return FLASHCART_ERROR_OUTDATED;
} else if (minor == SUPPORTED_MINOR_VERSION && revision < SUPPORTED_REVISION) {
return FLASHCART_ERROR_OUTDATED;
}
bool writeback_pending;
do {
if (sc64_writeback_pending(&writeback_pending) != SC64_OK) {
if (sc64_ll_writeback_pending(&writeback_pending) != SC64_OK) {
return FLASHCART_ERROR_INT;
}
} while (writeback_pending);
const struct {
sc64_cfg_t id;
sc64_cfg_id_t id;
uint32_t value;
} default_config[] = {
{ CFG_BOOTLOADER_SWITCH, false },
{ CFG_ROM_WRITE_ENABLE, false },
{ CFG_ROM_SHADOW_ENABLE, false },
{ CFG_DD_MODE, DD_MODE_DISABLED },
{ CFG_ISV_ADDRESS, 0x00000000 },
{ CFG_BOOT_MODE, BOOT_MODE_MENU },
{ CFG_SAVE_TYPE, SAVE_TYPE_NONE },
{ CFG_CIC_SEED, CIC_SEED_AUTO },
{ CFG_TV_TYPE, TV_TYPE_PASSTHROUGH },
{ CFG_DD_SD_ENABLE, false },
{ CFG_DD_DRIVE_TYPE, DRIVE_TYPE_RETAIL },
{ CFG_DD_DISK_STATE, DISK_STATE_EJECTED },
{ CFG_BUTTON_MODE, BUTTON_MODE_NONE },
{ CFG_ROM_EXTENDED_ENABLE, false },
{ CFG_ID_BOOTLOADER_SWITCH, false },
{ CFG_ID_ROM_WRITE_ENABLE, false },
{ CFG_ID_ROM_SHADOW_ENABLE, false },
{ CFG_ID_DD_MODE, DD_MODE_DISABLED },
{ CFG_ID_ISV_ADDRESS, 0x00000000 },
{ CFG_ID_BOOT_MODE, BOOT_MODE_MENU },
{ CFG_ID_SAVE_TYPE, SAVE_TYPE_NONE },
{ CFG_ID_CIC_SEED, CIC_SEED_AUTO },
{ CFG_ID_TV_TYPE, TV_TYPE_PASSTHROUGH },
{ CFG_ID_DD_SD_ENABLE, false },
{ CFG_ID_DD_DRIVE_TYPE, DRIVE_TYPE_RETAIL },
{ CFG_ID_DD_DISK_STATE, DISK_STATE_EJECTED },
{ CFG_ID_BUTTON_MODE, BUTTON_MODE_NONE },
{ CFG_ID_ROM_EXTENDED_ENABLE, false },
};
for (int i = 0; i < sizeof(default_config) / sizeof(default_config[0]); i++) {
if (sc64_set_config(default_config[i].id, default_config[i].value) != SC64_OK) {
if (sc64_ll_set_config(default_config[i].id, default_config[i].value) != SC64_OK) {
return FLASHCART_ERROR_INT;
}
}
@ -107,7 +110,7 @@ static flashcart_error_t sc64_init (void) {
}
static flashcart_error_t sc64_deinit (void) {
sc64_lock();
sc64_ll_lock();
return FLASHCART_OK;
}
@ -152,7 +155,7 @@ static flashcart_error_t sc64_load_rom (char *rom_path, flashcart_progress_callb
return FLASHCART_ERROR_LOAD;
}
if (sc64_set_config(CFG_ROM_SHADOW_ENABLE, shadow_enabled) != SC64_OK) {
if (sc64_ll_set_config(CFG_ID_ROM_SHADOW_ENABLE, shadow_enabled) != SC64_OK) {
f_close(&fil);
return FLASHCART_ERROR_INT;
}
@ -169,7 +172,7 @@ static flashcart_error_t sc64_load_rom (char *rom_path, flashcart_progress_callb
}
}
if (sc64_set_config(CFG_ROM_EXTENDED_ENABLE, extended_enabled) != SC64_OK) {
if (sc64_ll_set_config(CFG_ID_ROM_EXTENDED_ENABLE, extended_enabled) != SC64_OK) {
f_close(&fil);
return FLASHCART_ERROR_INT;
}
@ -197,7 +200,7 @@ static flashcart_error_t sc64_load_file (char *file_path, uint32_t start_offset_
FIL fil;
UINT br;
if (f_open(&fil, file_path, FA_READ) != FR_OK) {
if (f_open(&fil, strip_sd_prefix(file_path), FA_READ) != FR_OK) {
return FLASHCART_ERROR_LOAD;
}
@ -205,19 +208,24 @@ static flashcart_error_t sc64_load_file (char *file_path, uint32_t start_offset_
size_t file_size = f_size(&fil);
if (file_size > MiB(8)) { // FIXME: should be checked with the start offset address.
if (file_size > (MiB(64) - start_offset_address)) {
f_close(&fil);
return FLASHCART_ERROR_LOAD;
return FLASHCART_ERROR_ARGS;
}
if (f_read(&fil, (void *) (ROM_ADDRESS + start_offset_address), file_size, &br) != FR_OK) {
f_close(&fil);
return FLASHCART_ERROR_LOAD;
}
if (br != file_size) {
f_close(&fil);
return FLASHCART_ERROR_LOAD;
}
if (f_close(&fil) != FR_OK) {
return FLASHCART_ERROR_LOAD;
}
return FLASHCART_OK;
}
@ -225,7 +233,7 @@ static flashcart_error_t sc64_load_save (char *save_path) {
void *address = NULL;
uint32_t value;
if (sc64_get_config(CFG_SAVE_TYPE, &value) != SC64_OK) {
if (sc64_ll_get_config(CFG_ID_SAVE_TYPE, &value) != SC64_OK) {
return FLASHCART_ERROR_INT;
}
@ -300,7 +308,7 @@ static flashcart_error_t sc64_set_save_type (flashcart_save_type_t save_type) {
return FLASHCART_ERROR_ARGS;
}
if (sc64_set_config(CFG_SAVE_TYPE, type) != SC64_OK) {
if (sc64_ll_set_config(CFG_ID_SAVE_TYPE, type) != SC64_OK) {
return FLASHCART_ERROR_INT;
}
@ -310,7 +318,7 @@ static flashcart_error_t sc64_set_save_type (flashcart_save_type_t save_type) {
static flashcart_error_t sc64_set_save_writeback (uint32_t *sectors) {
pi_dma_write_data(sectors, SC64_BUFFERS->BUFFER, 1024);
if (sc64_writeback_enable(SC64_BUFFERS->BUFFER) != SC64_OK) {
if (sc64_ll_writeback_enable(SC64_BUFFERS->BUFFER) != SC64_OK) {
return FLASHCART_ERROR_INT;
}

View File

@ -1,6 +1,6 @@
/**
* @file flashcart.h
* @brief SC64 Flashcart Utilities
* @file sc64.h
* @brief SC64 flashcart support
* @ingroup flashcart
*/
@ -10,14 +10,15 @@
#include "../flashcart.h"
/**
* @addtogroup sc64
* @{
*/
flashcart_t *sc64_get_flashcart (void);
/** @} */ /* sc64 */
#endif

View File

@ -1,6 +1,6 @@
#include <libdragon.h>
#include "sc64_internal.h"
#include "sc64_ll.h"
typedef struct {
@ -36,7 +36,7 @@ typedef struct {
} sc64_cmd_t;
static sc64_error_t sc64_execute_cmd (sc64_cmd_t *cmd) {
static sc64_error_t sc64_ll_execute_cmd (sc64_cmd_t *cmd) {
io_write((uint32_t) (&SC64_REGS->DATA[0]), cmd->arg[0]);
io_write((uint32_t) (&SC64_REGS->DATA[1]), cmd->arg[1]);
@ -58,78 +58,78 @@ static sc64_error_t sc64_execute_cmd (sc64_cmd_t *cmd) {
}
void sc64_lock (void) {
void sc64_ll_lock (void) {
io_write((uint32_t) (&SC64_REGS->KEY), SC64_KEY_LOCK);
}
sc64_error_t sc64_get_version (uint16_t *major, uint16_t *minor, uint32_t *revision) {
sc64_error_t sc64_ll_get_version (uint16_t *major, uint16_t *minor, uint32_t *revision) {
sc64_cmd_t cmd = {
.id = CMD_ID_VERSION_GET
};
sc64_error_t error = sc64_execute_cmd(&cmd);
sc64_error_t error = sc64_ll_execute_cmd(&cmd);
*major = ((cmd.rsp[0] >> 16) & 0xFFFF);
*minor = (cmd.rsp[0] & 0xFFFF);
*revision = cmd.rsp[1];
return error;
}
sc64_error_t sc64_get_config (sc64_cfg_t id, uint32_t *value) {
sc64_error_t sc64_ll_get_config (sc64_cfg_id_t id, uint32_t *value) {
sc64_cmd_t cmd = {
.id = CMD_ID_CONFIG_GET,
.arg = { id }
};
sc64_error_t error = sc64_execute_cmd(&cmd);
sc64_error_t error = sc64_ll_execute_cmd(&cmd);
*value = cmd.rsp[1];
return error;
}
sc64_error_t sc64_set_config (sc64_cfg_t id, uint32_t value) {
sc64_error_t sc64_ll_set_config (sc64_cfg_id_t id, uint32_t value) {
sc64_cmd_t cmd = {
.id = CMD_ID_CONFIG_SET,
.arg = { id, value }
};
return sc64_execute_cmd(&cmd);
return sc64_ll_execute_cmd(&cmd);
}
sc64_error_t sc64_writeback_pending (bool *pending) {
sc64_error_t sc64_ll_writeback_pending (bool *pending) {
sc64_cmd_t cmd = {
.id = CMD_ID_WRITEBACK_PENDING
};
sc64_error_t error = sc64_execute_cmd(&cmd);
sc64_error_t error = sc64_ll_execute_cmd(&cmd);
*pending = (cmd.rsp[0] != 0);
return error;
}
sc64_error_t sc64_writeback_enable (void *address) {
sc64_error_t sc64_ll_writeback_enable (void *address) {
sc64_cmd_t cmd = {
.id = CMD_ID_WRITEBACK_SD_INFO,
.arg = { (uint32_t) (address) }
};
return sc64_execute_cmd(&cmd);
return sc64_ll_execute_cmd(&cmd);
}
sc64_error_t sc64_flash_wait_busy (void) {
sc64_error_t sc64_ll_flash_wait_busy (void) {
sc64_cmd_t cmd = {
.id = CMD_ID_FLASH_WAIT_BUSY,
.arg = { true }
};
return sc64_execute_cmd(&cmd);
return sc64_ll_execute_cmd(&cmd);
}
sc64_error_t sc64_flash_get_erase_block_size (size_t *erase_block_size) {
sc64_error_t sc64_ll_flash_get_erase_block_size (size_t *erase_block_size) {
sc64_cmd_t cmd = {
.id = CMD_ID_FLASH_WAIT_BUSY,
.arg = { false }
};
sc64_error_t error = sc64_execute_cmd(&cmd);
sc64_error_t error = sc64_ll_execute_cmd(&cmd);
*erase_block_size = (size_t) (cmd.rsp[0]);
return error;
}
sc64_error_t sc64_flash_erase_block (void *address) {
sc64_error_t sc64_ll_flash_erase_block (void *address) {
sc64_cmd_t cmd = {
.id = CMD_ID_FLASH_ERASE_BLOCK,
.arg = { (uint32_t) (address) }
};
return sc64_execute_cmd(&cmd);
return sc64_ll_execute_cmd(&cmd);
}

View File

@ -1,16 +1,17 @@
/**
* @file flashcart.h
* @brief SC64 Flashcart Internal Utilities
* @ingroup flashcart
* @file sc64_ll.h
* @brief SC64 flashcart low level access
* @ingroup flashcart
*/
#ifndef FLASHCART_SC64_INTERNAL_H__
#define FLASHCART_SC64_INTERNAL_H__
#ifndef FLASHCART_SC64_LL_H__
#define FLASHCART_SC64_LL_H__
#include <stddef.h>
#include <stdint.h>
/**
* @addtogroup sc64
* @{
@ -38,22 +39,22 @@ typedef enum {
} sc64_error_t;
typedef enum {
CFG_BOOTLOADER_SWITCH,
CFG_ROM_WRITE_ENABLE,
CFG_ROM_SHADOW_ENABLE,
CFG_DD_MODE,
CFG_ISV_ADDRESS,
CFG_BOOT_MODE,
CFG_SAVE_TYPE,
CFG_CIC_SEED,
CFG_TV_TYPE,
CFG_DD_SD_ENABLE,
CFG_DD_DRIVE_TYPE,
CFG_DD_DISK_STATE,
CFG_BUTTON_STATE,
CFG_BUTTON_MODE,
CFG_ROM_EXTENDED_ENABLE,
} sc64_cfg_t;
CFG_ID_BOOTLOADER_SWITCH,
CFG_ID_ROM_WRITE_ENABLE,
CFG_ID_ROM_SHADOW_ENABLE,
CFG_ID_DD_MODE,
CFG_ID_ISV_ADDRESS,
CFG_ID_BOOT_MODE,
CFG_ID_SAVE_TYPE,
CFG_ID_CIC_SEED,
CFG_ID_TV_TYPE,
CFG_ID_DD_SD_ENABLE,
CFG_ID_DD_DRIVE_TYPE,
CFG_ID_DD_DISK_STATE,
CFG_ID_BUTTON_STATE,
CFG_ID_BUTTON_MODE,
CFG_ID_ROM_EXTENDED_ENABLE,
} sc64_cfg_id_t;
typedef enum {
DD_MODE_DISABLED = 0,
@ -110,16 +111,17 @@ typedef enum {
} sc64_button_mode_t;
void sc64_lock (void);
sc64_error_t sc64_get_version (uint16_t *major, uint16_t *minor, uint32_t *revision);
sc64_error_t sc64_get_config (sc64_cfg_t cfg, uint32_t *value);
sc64_error_t sc64_set_config (sc64_cfg_t cfg, uint32_t value);
sc64_error_t sc64_writeback_pending (bool *pending);
sc64_error_t sc64_writeback_enable (void *address);
sc64_error_t sc64_flash_wait_busy (void);
sc64_error_t sc64_flash_get_erase_block_size (size_t *erase_block_size);
sc64_error_t sc64_flash_erase_block (void *address);
void sc64_ll_lock (void);
sc64_error_t sc64_ll_get_version (uint16_t *major, uint16_t *minor, uint32_t *revision);
sc64_error_t sc64_ll_get_config (sc64_cfg_id_t cfg, uint32_t *value);
sc64_error_t sc64_ll_set_config (sc64_cfg_id_t cfg, uint32_t value);
sc64_error_t sc64_ll_writeback_pending (bool *pending);
sc64_error_t sc64_ll_writeback_enable (void *address);
sc64_error_t sc64_ll_flash_wait_busy (void);
sc64_error_t sc64_ll_flash_get_erase_block_size (size_t *erase_block_size);
sc64_error_t sc64_ll_flash_erase_block (void *address);
/** @} */ /* sc64 */
#endif