From f09416861de41b95b765faa75bc89841fe1bf764 Mon Sep 17 00:00:00 2001 From: Robin Jones Date: Tue, 22 Aug 2023 00:16:35 +0100 Subject: [PATCH] Minimal ED64 support Adds the basic needs to run ROMs on V series hardware. --- Makefile | 2 + README.md | 8 +- src/flashcart/ed64/README.md | 1 + src/flashcart/ed64/ed64.c | 211 +++++++++++++++++++++++++++++++++++ src/flashcart/ed64/ed64.h | 24 ++++ src/flashcart/ed64/ed64_ll.c | 116 +++++++++++++++++++ src/flashcart/ed64/ed64_ll.h | 43 +++++++ src/flashcart/flashcart.c | 3 +- 8 files changed, 404 insertions(+), 4 deletions(-) create mode 100644 src/flashcart/ed64/README.md create mode 100644 src/flashcart/ed64/ed64.c create mode 100644 src/flashcart/ed64/ed64.h create mode 100644 src/flashcart/ed64/ed64_ll.c create mode 100644 src/flashcart/ed64/ed64_ll.h diff --git a/Makefile b/Makefile index e9e8ce00..7cbbcf11 100644 --- a/Makefile +++ b/Makefile @@ -20,6 +20,8 @@ SRCS = \ flashcart/flashcart.c \ flashcart/sc64/sc64_ll.c \ flashcart/sc64/sc64.c \ + flashcart/ed64/ed64_ll.c \ + flashcart/ed64/ed64.c \ hdmi/hdmi.c \ libs/libspng/spng/spng.c \ libs/mini.c/src/mini.c \ diff --git a/README.md b/README.md index 23d439df..5482d178 100644 --- a/README.md +++ b/README.md @@ -28,9 +28,11 @@ Ensure the cart is running the latest [firmware](https://github.com/Polprzewodni Download the `sc64menu.n64` ROM from the latest action run assets. Add it to the root folder on your SD card. -### ED64 & ED64P -Currently not supported, but there is an aim to do so. -The aim is to replace [Altra64](https://github.com/networkfusion/altra64) and [ED64-UnofficialOS](https://github.com/n64-tools/ED64-UnofficialOS-binaries). +### ED64 +Download the `ED64.v64` ROM from the latest action run assets and place it in the `/ED64` folder. + +### ED64P +Download the `ED64P.v64` ROM from the latest action run assets and place it in the `/ED64P` folder. ### Common to all diff --git a/src/flashcart/ed64/README.md b/src/flashcart/ed64/README.md new file mode 100644 index 00000000..41bd285b --- /dev/null +++ b/src/flashcart/ed64/README.md @@ -0,0 +1 @@ +This folder allows support for the ED64(P) flashcart when using V series hardware. \ No newline at end of file diff --git a/src/flashcart/ed64/ed64.c b/src/flashcart/ed64/ed64.c new file mode 100644 index 00000000..25c95f01 --- /dev/null +++ b/src/flashcart/ed64/ed64.c @@ -0,0 +1,211 @@ +#include +#include +#include + +#include +#include + +#include "utils/fs.h" +#include "utils/utils.h" + +#include "../flashcart_utils.h" +#include "ed64_ll.h" +#include "ed64.h" + +#define EEPROM_ADDRESS (0x1FFE2000) + +extern int ed_exit(void); + +static flashcart_error_t ed64_init (void) { + + // TODO: partly already done, see https://github.com/DragonMinded/libdragon/blob/4ec469d26b6dc4e308caf3d5b86c2b340b708bbd/src/libcart/cart.c#L1064 + + // FIXME: Update firmware if needed. + // FIXME: Enable RTC if available. + + return FLASHCART_OK; +} + +static flashcart_error_t ed64_deinit (void) { + + // For the moment, just use libCart exit. + ed_exit(); + + return FLASHCART_OK; +} + +static flashcart_error_t ed64_load_rom (char *rom_path, flashcart_progress_callback_t *progress) { + FIL fil; + UINT br; + + if (f_open(&fil, strip_sd_prefix(rom_path), FA_READ) != FR_OK) { + return FLASHCART_ERROR_LOAD; + } + + fix_file_size(&fil); + + size_t rom_size = f_size(&fil); + + // FIXME: if the cart is not V3 or X5 or X7, we need to - 128KiB + if (rom_size > MiB(64) - KiB(128)) { + f_close(&fil); + return FLASHCART_ERROR_LOAD; + } + + + size_t sdram_size = rom_size; + + size_t chunk_size = MiB(1); + for (int offset = 0; offset < sdram_size; offset += chunk_size) { + size_t block_size = MIN(sdram_size - offset, chunk_size); + if (f_read(&fil, (void *) (ROM_ADDRESS + offset), block_size, &br) != FR_OK) { + f_close(&fil); + return FLASHCART_ERROR_LOAD; + } + if (progress) { + progress(f_tell(&fil) / (float) (f_size(&fil))); + } + } + if (f_tell(&fil) != sdram_size) { + f_close(&fil); + return FLASHCART_ERROR_LOAD; + } + + + if (f_close(&fil) != FR_OK) { + return FLASHCART_ERROR_LOAD; + } + + return FLASHCART_OK; +} + +static flashcart_error_t ed64_load_file (char *file_path, uint32_t rom_offset, uint32_t file_offset) { + FIL fil; + UINT br; + + if (f_open(&fil, strip_sd_prefix(file_path), FA_READ) != FR_OK) { + return FLASHCART_ERROR_LOAD; + } + + fix_file_size(&fil); + + size_t file_size = f_size(&fil) - file_offset; + + // FIXME: if the cart is not V3 or X5 or X7, we need to - 128KiB + if (file_size > (MiB(64) - KiB(128) - rom_offset)) { + f_close(&fil); + return FLASHCART_ERROR_ARGS; + } + + if (f_lseek(&fil, file_offset) != FR_OK) { + f_close(&fil); + return FLASHCART_ERROR_LOAD; + } + + if (f_read(&fil, (void *) (ROM_ADDRESS + rom_offset), 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; +} + +static flashcart_error_t ed64_load_save (char *save_path) { + void *address = NULL; + ed64_save_type_t type = ed64_ll_get_save_type(); + + switch (type) { + case SAVE_TYPE_EEPROM_4K: + case SAVE_TYPE_EEPROM_16K: + address = (void *) (EEPROM_ADDRESS); + break; + case SAVE_TYPE_SRAM: + case SAVE_TYPE_SRAM_128K: + case SAVE_TYPE_FLASHRAM: + address = (void *) (SRAM_ADDRESS); + break; + case SAVE_TYPE_NONE: + default: + return FLASHCART_ERROR_ARGS; + } + + FIL fil; + UINT br; + + if (f_open(&fil, strip_sd_prefix(save_path), FA_READ) != FR_OK) { + return FLASHCART_ERROR_LOAD; + } + + size_t save_size = f_size(&fil); + + if (f_read(&fil, address, save_size, &br) != FR_OK) { + f_close(&fil); + return FLASHCART_ERROR_LOAD; + } + + if (f_close(&fil) != FR_OK) { + return FLASHCART_ERROR_LOAD; + } + + if (br != save_size) { + return FLASHCART_ERROR_LOAD; + } + + return FLASHCART_OK; +} + +static flashcart_error_t ed64_set_save_type (flashcart_save_type_t save_type) { + ed64_save_type_t type; + + switch (save_type) { + case FLASHCART_SAVE_TYPE_NONE: + type = SAVE_TYPE_NONE; + break; + case FLASHCART_SAVE_TYPE_EEPROM_4K: + type = SAVE_TYPE_EEPROM_4K; + break; + case FLASHCART_SAVE_TYPE_EEPROM_16K: + type = SAVE_TYPE_EEPROM_16K; + break; + case FLASHCART_SAVE_TYPE_SRAM: + type = SAVE_TYPE_SRAM; + break; + case FLASHCART_SAVE_TYPE_SRAM_BANKED: + case FLASHCART_SAVE_TYPE_SRAM_128K: + type = SAVE_TYPE_SRAM_128K; + break; + case FLASHCART_SAVE_TYPE_FLASHRAM: + type = SAVE_TYPE_FLASHRAM; + break; + default: + return FLASHCART_ERROR_ARGS; + } + + ed64_ll_set_save_type(type); + + return FLASHCART_OK; +} + + +static flashcart_t flashcart_ed64 = { + .init = ed64_init, + .deinit = ed64_deinit, + .load_rom = ed64_load_rom, + .load_file = ed64_load_file, + .load_save = ed64_load_save, + .set_save_type = ed64_set_save_type, + .set_save_writeback = NULL, +}; + + +flashcart_t *ed64_get_flashcart (void) { + return &flashcart_ed64; +} diff --git a/src/flashcart/ed64/ed64.h b/src/flashcart/ed64/ed64.h new file mode 100644 index 00000000..4738140f --- /dev/null +++ b/src/flashcart/ed64/ed64.h @@ -0,0 +1,24 @@ +/** + * @file flashcart.h + * @brief ED64 Flashcart Utilities + * @ingroup flashcart + */ + +#ifndef FLASHCART_ED64_H__ +#define FLASHCART_ED64_H__ + + +#include "../flashcart.h" + + +/** + * @addtogroup ed64 + * @{ + */ + +flashcart_t *ed64_get_flashcart (void); + +/** @} */ /* ed64 */ + + +#endif diff --git a/src/flashcart/ed64/ed64_ll.c b/src/flashcart/ed64/ed64_ll.c new file mode 100644 index 00000000..3eaa70b1 --- /dev/null +++ b/src/flashcart/ed64/ed64_ll.c @@ -0,0 +1,116 @@ +#include + +#include "ed64_ll.h" + + +/* ED64 configuration registers base address */ +#define ED64_CONFIG_REGS_BASE (0xA8040000) + +typedef enum { + // REG_CFG = 0, + // REG_STATUS = 1, + // REG_DMA_LENGTH = 2, + // REG_DMA_RAM_ADDR = 3, + // REG_MSG = 4, + // REG_DMA_CFG = 5, + // REG_SPI = 6, + // REG_SPI_CFG = 7, + // REG_KEY = 8, + REG_SAV_CFG = 9, + // REG_SEC = 10, /* Sectors?? */ + // REG_FPGA_VERSION = 11, /* Altera (Intel) MAX */ + // REG_GPIO = 12, + +} ed64_registers_t; + + +#define SAV_EEP_ON 1 +#define SAV_SRM_ON 2 +#define SAV_EEP_SIZE 4 +#define SAV_SRM_SIZE 8 + +#define SAV_RAM_BANK 128 +#define SAV_RAM_BANK_APPLY 32768 + +uint32_t ed64_ll_reg_read(uint32_t reg); +void ed64_ll_reg_write(uint32_t reg, uint32_t data); + +uint8_t ed64_ll_sram_bank; +ed64_save_type_t ed64_ll_save_type; + + +uint32_t ed64_ll_reg_read(uint32_t reg) { + + *(volatile uint32_t *) (ED64_CONFIG_REGS_BASE); + return *(volatile uint32_t *) (ED64_CONFIG_REGS_BASE + reg * 4); +} + +void ed64_ll_reg_write(uint32_t reg, uint32_t data) { + + *(volatile uint32_t *) (ED64_CONFIG_REGS_BASE); + *(volatile uint32_t *) (ED64_CONFIG_REGS_BASE + reg * 4) = data; + *(volatile uint32_t *) (ROM_ADDRESS); + +} + + +ed64_save_type_t ed64_ll_get_save_type() { + + return ed64_ll_save_type; +} + +void ed64_ll_set_save_type(ed64_save_type_t type) { + + uint16_t save_cfg; + uint8_t eeprom_on, sram_on, eeprom_size, sram_size, ram_bank; + ed64_ll_save_type = type; + eeprom_on = 0; + sram_on = 0; + eeprom_size = 0; + sram_size = 0; + ram_bank = ed64_ll_sram_bank; + + + switch (type) { + case SAVE_TYPE_EEPROM_16K: + eeprom_on = 1; + eeprom_size = 1; + break; + case SAVE_TYPE_EEPROM_4K: + eeprom_on = 1; + break; + case SAVE_TYPE_SRAM: + sram_on = 1; + break; + case SAVE_TYPE_SRAM_128K: + sram_on = 1; + sram_size = 1; + break; + case SAVE_TYPE_FLASHRAM: + sram_on = 0; + sram_size = 1; + break; + default: + sram_on = 0; + sram_size = 0; + ram_bank = 1; + break; + } + + save_cfg = 0; + if (eeprom_on)save_cfg |= SAV_EEP_ON; + if (sram_on)save_cfg |= SAV_SRM_ON; + if (eeprom_size)save_cfg |= SAV_EEP_SIZE; + if (sram_size)save_cfg |= SAV_SRM_SIZE; + if (ram_bank)save_cfg |= SAV_RAM_BANK; + save_cfg |= SAV_RAM_BANK_APPLY; + + ed64_ll_reg_write(REG_SAV_CFG, save_cfg); + +} + +void ed64_ll_set_sram_bank(uint8_t bank) { + + ed64_ll_sram_bank = bank == 0 ? 0 : 1; + +} diff --git a/src/flashcart/ed64/ed64_ll.h b/src/flashcart/ed64/ed64_ll.h new file mode 100644 index 00000000..0faa635d --- /dev/null +++ b/src/flashcart/ed64/ed64_ll.h @@ -0,0 +1,43 @@ +/** + * @file flashcart.h + * @brief ED64 V-Series Flashcart Internal Utilities + * @ingroup flashcart + */ + +#ifndef FLASHCART_ED64_LL_H__ +#define FLASHCART_ED64_LL_H__ + + +#include +#include +#include + +/** + * @addtogroup ed64 + * @{ + */ + + +typedef enum { + SAVE_TYPE_NONE = 0, + SAVE_TYPE_SRAM = 1, + SAVE_TYPE_SRAM_128K = 2, + SAVE_TYPE_EEPROM_4K = 3, + SAVE_TYPE_EEPROM_16K = 4, + SAVE_TYPE_FLASHRAM = 5, + SAVE_TYPE_CPAK = 8, + SAVE_TYPE_DD64 = 16, +} ed64_save_type_t; + + +#define SRAM_ADDRESS (0xA8000000) +#define ROM_ADDRESS (0xB0000000) + +/* Save functions */ +void ed64_ll_set_ram_bank(uint8_t bank); +ed64_save_type_t ed64_ll_get_save_type(); +void ed64_ll_set_save_type(ed64_save_type_t type); + +/** @} */ /* ed64 */ + +#endif diff --git a/src/flashcart/flashcart.c b/src/flashcart/flashcart.c index 81052ca6..85e60eec 100644 --- a/src/flashcart/flashcart.c +++ b/src/flashcart/flashcart.c @@ -9,6 +9,7 @@ #include "flashcart.h" #include "sc64/sc64.h" +#include "ed64/ed64.h" #define WRITEBACK_MAX_SECTORS (256) @@ -58,7 +59,7 @@ flashcart_error_t flashcart_init (void) { { CART_CI, ci_init, NULL }, // 64drive { CART_SC, sc_init, sc64_get_flashcart }, // SC64 { CART_EDX, edx_init, NULL }, // Series X EverDrive-64 - { CART_ED, ed_init, NULL }, // Original EverDrive-64 + { CART_ED, ed_init, ed64_get_flashcart }, // Original EverDrive-64 }; for (int i = 0; i < CART_MAX; i++) {