Minimal ED64 support

Adds the basic needs to run ROMs on V series hardware.
This commit is contained in:
Robin Jones 2023-08-22 00:16:35 +01:00
parent 7797f74c0b
commit f09416861d
8 changed files with 404 additions and 4 deletions

View File

@ -20,6 +20,8 @@ SRCS = \
flashcart/flashcart.c \ flashcart/flashcart.c \
flashcart/sc64/sc64_ll.c \ flashcart/sc64/sc64_ll.c \
flashcart/sc64/sc64.c \ flashcart/sc64/sc64.c \
flashcart/ed64/ed64_ll.c \
flashcart/ed64/ed64.c \
hdmi/hdmi.c \ hdmi/hdmi.c \
libs/libspng/spng/spng.c \ libs/libspng/spng/spng.c \
libs/mini.c/src/mini.c \ libs/mini.c/src/mini.c \

View File

@ -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. Download the `sc64menu.n64` ROM from the latest action run assets.
Add it to the root folder on your SD card. Add it to the root folder on your SD card.
### ED64 & ED64P ### ED64
Currently not supported, but there is an aim to do so. Download the `ED64.v64` ROM from the latest action run assets and place it in the `/ED64` folder.
The aim is to replace [Altra64](https://github.com/networkfusion/altra64) and [ED64-UnofficialOS](https://github.com/n64-tools/ED64-UnofficialOS-binaries).
### ED64P
Download the `ED64P.v64` ROM from the latest action run assets and place it in the `/ED64P` folder.
### Common to all ### Common to all

View File

@ -0,0 +1 @@
This folder allows support for the ED64(P) flashcart when using V series hardware.

211
src/flashcart/ed64/ed64.c Normal file
View File

@ -0,0 +1,211 @@
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <fatfs/ff.h>
#include <libdragon.h>
#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;
}

24
src/flashcart/ed64/ed64.h Normal file
View File

@ -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

View File

@ -0,0 +1,116 @@
#include <libdragon.h>
#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;
}

View File

@ -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 <stddef.h>
#include <stdint.h>
#include <stdbool.h>
/**
* @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

View File

@ -9,6 +9,7 @@
#include "flashcart.h" #include "flashcart.h"
#include "sc64/sc64.h" #include "sc64/sc64.h"
#include "ed64/ed64.h"
#define WRITEBACK_MAX_SECTORS (256) #define WRITEBACK_MAX_SECTORS (256)
@ -58,7 +59,7 @@ flashcart_error_t flashcart_init (void) {
{ CART_CI, ci_init, NULL }, // 64drive { CART_CI, ci_init, NULL }, // 64drive
{ CART_SC, sc_init, sc64_get_flashcart }, // SC64 { CART_SC, sc_init, sc64_get_flashcart }, // SC64
{ CART_EDX, edx_init, NULL }, // Series X EverDrive-64 { 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++) { for (int i = 0; i < CART_MAX; i++) {