Skip to content

Commit

Permalink
Minimal ED64 support
Browse files Browse the repository at this point in the history
Adds the basic needs to run ROMs on V series hardware.
  • Loading branch information
networkfusion committed Aug 21, 2023
1 parent 7797f74 commit f094168
Show file tree
Hide file tree
Showing 8 changed files with 404 additions and 4 deletions.
2 changes: 2 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -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 \
Expand Down
8 changes: 5 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions src/flashcart/ed64/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
This folder allows support for the ED64(P) flashcart when using V series hardware.
211 changes: 211 additions & 0 deletions src/flashcart/ed64/ed64.c
Original file line number Diff line number Diff line change
@@ -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 changes: 24 additions & 0 deletions src/flashcart/ed64/ed64.h
Original file line number Diff line number Diff line change
@@ -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
116 changes: 116 additions & 0 deletions src/flashcart/ed64/ed64_ll.c
Original file line number Diff line number Diff line change
@@ -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;

}
Loading

0 comments on commit f094168

Please sign in to comment.