diff --git a/src/flashcart/ed64/ed64.c b/src/flashcart/ed64/ed64.c index 313722ab..c8d7cce7 100644 --- a/src/flashcart/ed64/ed64.c +++ b/src/flashcart/ed64/ed64.c @@ -18,17 +18,23 @@ extern int ed_exit(void); static flashcart_err_t ed64_init (void) { // TODO: partly already done, see https://github.com/DragonMinded/libdragon/blob/4ec469d26b6dc4e308caf3d5b86c2b340b708bbd/src/libcart/cart.c#L1064 + FIL fil, rsfil; + UINT br; + if (f_open(&rsfil, strip_sd_prefix("/menu/RESET"), FA_READ | FA_OPEN_EXISTING) == FR_OK) { + f_close(&rsfil); + f_unlink(strip_sd_prefix("/menu/RESET")); + int size = KiB(128); + uint8_t cartsave_data[size]; + f_open(&fil, strip_sd_prefix("test.sav"), FA_WRITE | FA_CREATE_NEW); + getSRAM(cartsave_data, size); + f_write(&fil, cartsave_data, size, &br); + f_close(&fil); + } - // FIXME: Update firmware if needed. - // FIXME: Enable RTC if available. - - // FIXME: retrive a config file from (probably SRAM) that might have been set. - // This should include the location of the ROM and its save type. - // Then, if it is valid, perform a save. - return FLASHCART_OK; } + static flashcart_err_t ed64_deinit (void) { // For the moment, just use libCart exit. @@ -134,43 +140,32 @@ static flashcart_err_t ed64_load_file (char *file_path, uint32_t rom_offset, uin } static flashcart_err_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: - 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_ERR_ARGS; - } - + //ed64_save_type_t type = ed64_ll_get_save_type(); FIL fil; UINT br; - if (f_open(&fil, strip_sd_prefix(save_path), FA_READ) != FR_OK) { - return FLASHCART_ERR_LOAD; - } + if (f_open(&fil, strip_sd_prefix("test.sav"), FA_READ) == FR_OK) { - size_t save_size = f_size(&fil); + size_t save_size = KiB(128); + uint8_t cartsave_data[save_size]; - if (f_read(&fil, address, save_size, &br) != FR_OK) { - f_close(&fil); - return FLASHCART_ERR_LOAD; + if (f_read(&fil, cartsave_data, save_size, &br) != FR_OK) { + f_close(&fil); + return FLASHCART_ERR_LOAD; } if (f_close(&fil) != FR_OK) { return FLASHCART_ERR_LOAD; } - if (br != save_size) { - return FLASHCART_ERR_LOAD; - } + setSRAM(cartsave_data, save_size); +} + FIL rsfil; + UINT rsbr; + TCHAR byte[1]; + f_open(&rsfil, strip_sd_prefix("/menu/RESET"), FA_WRITE | FA_CREATE_ALWAYS); + f_write(&rsfil, (void *)byte, 1, &rsbr); + f_close(&rsfil); return FLASHCART_OK; } diff --git a/src/flashcart/ed64/ed64_ll.c b/src/flashcart/ed64/ed64_ll.c index 3eaa70b1..fa9b6328 100644 --- a/src/flashcart/ed64/ed64_ll.c +++ b/src/flashcart/ed64/ed64_ll.c @@ -114,3 +114,200 @@ void ed64_ll_set_sram_bank(uint8_t bank) { ed64_ll_sram_bank = bank == 0 ? 0 : 1; } + + +#include +#include +#include +#include "types.h" + + +void PI_Init(void) { + PI_DMAWait(); + IO_WRITE(PI_STATUS_REG, 0x03); +} + +// Inits PI for sram transfer +void PI_Init_SRAM(void) { + + IO_WRITE(PI_BSD_DOM2_LAT_REG, 0x05); + IO_WRITE(PI_BSD_DOM2_PWD_REG, 0x0C); + IO_WRITE(PI_BSD_DOM2_PGS_REG, 0x0D); + IO_WRITE(PI_BSD_DOM2_RLS_REG, 0x02); + +} + +void PI_DMAWait(void) { + + while (IO_READ(PI_STATUS_REG) & (PI_STATUS_IO_BUSY | PI_STATUS_DMA_BUSY)); +} + + +void PI_DMAFromSRAM(void *dest, u32 offset, u32 size) { + + + IO_WRITE(PI_DRAM_ADDR_REG, K1_TO_PHYS(dest)); + IO_WRITE(PI_CART_ADDR_REG, (0xA8000000 + offset)); + asm volatile ("" : : : "memory"); + IO_WRITE(PI_WR_LEN_REG, (size - 1)); + asm volatile ("" : : : "memory"); + +} + + +void PI_DMAToSRAM(void *src, u32 offset, u32 size) { //void* + PI_DMAWait(); + + IO_WRITE(PI_STATUS_REG, 2); + IO_WRITE(PI_DRAM_ADDR_REG, K1_TO_PHYS(src)); + IO_WRITE(PI_CART_ADDR_REG, (0xA8000000 + offset)); + IO_WRITE(PI_RD_LEN_REG, (size - 1)); +} + +void PI_DMAFromCart(void* dest, void* src, u32 size) { + PI_DMAWait(); + + IO_WRITE(PI_STATUS_REG, 0x03); + IO_WRITE(PI_DRAM_ADDR_REG, K1_TO_PHYS(dest)); + IO_WRITE(PI_CART_ADDR_REG, K0_TO_PHYS(src)); + IO_WRITE(PI_WR_LEN_REG, (size - 1)); +} + + +void PI_DMAToCart(void* dest, void* src, u32 size) { + PI_DMAWait(); + + IO_WRITE(PI_STATUS_REG, 0x02); + IO_WRITE(PI_DRAM_ADDR_REG, K1_TO_PHYS(src)); + IO_WRITE(PI_CART_ADDR_REG, K0_TO_PHYS(dest)); + IO_WRITE(PI_RD_LEN_REG, (size - 1)); +} + + +// Wrapper to support unaligned access to memory +void PI_SafeDMAFromCart(void *dest, void *src, u32 size) { + if (!dest || !src || !size) return; + + u32 unalignedSrc = ((u32)src) % 2; + u32 unalignedDest = ((u32)dest) % 8; + + //FIXME: Do i really need to check if size is 16bit aligned? + if (!unalignedDest && !unalignedSrc && !(size % 2)) { + PI_DMAFromCart(dest, src, size); + PI_DMAWait(); + + return; + } + + void* newSrc = (void*)(((u32)src) - unalignedSrc); + u32 newSize = (size + unalignedSrc) + ((size + unalignedSrc) % 2); + + u8 *buffer = memalign(8, newSize); + PI_DMAFromCart(buffer, newSrc, newSize); + PI_DMAWait(); + + memcpy(dest, (buffer + unalignedSrc), size); + + free(buffer); +} + +#include "types.h" + +int getSRAM( uint8_t *buffer, int size){ + while (dma_busy()) ; + + IO_WRITE(PI_BSD_DOM2_LAT_REG, 0x05); + IO_WRITE(PI_BSD_DOM2_PWD_REG, 0x0C); + IO_WRITE(PI_BSD_DOM2_PGS_REG, 0x0D); + IO_WRITE(PI_BSD_DOM2_RLS_REG, 0x02); + + while (dma_busy()) ; + + PI_Init(); + + while (dma_busy()) ; + + PI_DMAFromSRAM(buffer, 0, size) ; + + while (dma_busy()) ; + + IO_WRITE(PI_BSD_DOM2_LAT_REG, 0x40); + IO_WRITE(PI_BSD_DOM2_PWD_REG, 0x12); + IO_WRITE(PI_BSD_DOM2_PGS_REG, 0x07); + IO_WRITE(PI_BSD_DOM2_RLS_REG, 0x03); + + return 1; +} + +int getEeprom( uint8_t *buffer){ + int blocks=(16*1024)/8; + for( int b = 0; b < blocks; b++ ) { + eeprom_read( b, &buffer[b * 8] ); + } + + return 1; +} + + +/* +sram upload +*/ +int setSRAM( uint8_t *buffer,int size){ + //half working + PI_DMAWait(); + //Timing + PI_Init_SRAM(); + + //Readmode + PI_Init(); + + data_cache_hit_writeback_invalidate(buffer,size); + while (dma_busy()); + PI_DMAToSRAM(buffer, 0, size); + data_cache_hit_writeback_invalidate(buffer,size); + + //Wait + PI_DMAWait(); + //Restore evd Timing + setSDTiming(); + + return 1; +} + + +int setEeprom(uint8_t *buffer){ + int blocks=(16*1024)/8; + for( int b = 0; b < blocks; b++ ) { + eeprom_write( b, &buffer[b * 8] ); + } + + return 1; +} + +void setSDTiming(void){ + + // PI_DMAWait(); + IO_WRITE(PI_BSD_DOM1_LAT_REG, 0x40); + IO_WRITE(PI_BSD_DOM1_PWD_REG, 0x12); + IO_WRITE(PI_BSD_DOM1_PGS_REG, 0x07); + IO_WRITE(PI_BSD_DOM1_RLS_REG, 0x03); + + IO_WRITE(PI_BSD_DOM2_LAT_REG, 0x40); + IO_WRITE(PI_BSD_DOM2_PWD_REG, 0x12); + IO_WRITE(PI_BSD_DOM2_PGS_REG, 0x07); + IO_WRITE(PI_BSD_DOM2_RLS_REG, 0x03); +} + + +void restoreTiming(void) { + //n64 timing restore :> + IO_WRITE(PI_BSD_DOM1_LAT_REG, 0x40); + IO_WRITE(PI_BSD_DOM1_PWD_REG, 0x12); + IO_WRITE(PI_BSD_DOM1_PGS_REG, 0x07); + IO_WRITE(PI_BSD_DOM1_RLS_REG, 0x03); + + IO_WRITE(PI_BSD_DOM2_LAT_REG, 0x40); + IO_WRITE(PI_BSD_DOM2_PWD_REG, 0x12); + IO_WRITE(PI_BSD_DOM2_PGS_REG, 0x07); + IO_WRITE(PI_BSD_DOM2_RLS_REG, 0x03); +} diff --git a/src/flashcart/ed64/ed64_ll.h b/src/flashcart/ed64/ed64_ll.h index 1e8f3cf0..30bc032d 100644 --- a/src/flashcart/ed64/ed64_ll.h +++ b/src/flashcart/ed64/ed64_ll.h @@ -7,10 +7,11 @@ #ifndef FLASHCART_ED64_LL_H__ #define FLASHCART_ED64_LL_H__ - +#include #include #include #include +#include "types.h" /** * @addtogroup ed64 @@ -40,4 +41,150 @@ void ed64_ll_set_save_type(ed64_save_type_t type); /** @} */ /* ed64 */ + +//sram.h + +void data_cache_hit_writeback_invalidate(volatile void *, unsigned long); +unsigned int CRC_Calculate(unsigned int crc, unsigned char* buf, unsigned int len); +void dma_write_sram(void* src, u32 offset, u32 size); +void dma_read_sram(void *dest, u32 offset, u32 size); +void dma_write_s(void * ram_address, unsigned long pi_address, unsigned long len); +void dma_read_s(void * ram_address, unsigned long pi_address, unsigned long len); +int writeSram(void* src, u32 size); +void setSDTiming(void); + + +void PI_Init(void); +void PI_Init_SRAM(void); +void PI_DMAWait(void); +void PI_DMAFromCart(void* dest, void* src, u32 size); +void PI_DMAToCart(void* dest, void* src, u32 size); +void PI_DMAFromSRAM(void *dest, u32 offset, u32 size); +void PI_DMAToSRAM(void* src, u32 offset, u32 size); +void PI_SafeDMAFromCart(void *dest, void *src, u32 size); + +//memory +/*** MEMORY ***/ +void *safe_memalign(size_t boundary, size_t size); +void *safe_calloc(size_t nmemb, size_t size); +void *safe_malloc(size_t size); +void safe_free(void *ptr); +void *safe_memset(void *s, int c, size_t n); +void *safe_memcpy(void *dest, const void *src, size_t n); + + +#define DP_BASE_REG 0x04100000 +#define VI_BASE_REG 0x04400000 +#define PI_BASE_REG 0x04600000 +#define PIF_RAM_START 0x1FC007C0 + + +/* + * PI status register has 3 bits active when read from (PI_STATUS_REG - read) + * Bit 0: DMA busy - set when DMA is in progress + * Bit 1: IO busy - set when IO is in progress + * Bit 2: Error - set when CPU issues IO request while DMA is busy + */ + +#define PI_STATUS_REG (PI_BASE_REG+0x10) + +/* PI DRAM address (R/W): starting RDRAM address */ +#define PI_DRAM_ADDR_REG (PI_BASE_REG+0x00) /* DRAM address */ + +/* PI pbus (cartridge) address (R/W): starting AD16 address */ +#define PI_CART_ADDR_REG (PI_BASE_REG+0x04) + +/* PI read length (R/W): read data length */ +#define PI_RD_LEN_REG (PI_BASE_REG+0x08) + +/* PI write length (R/W): write data length */ +#define PI_WR_LEN_REG (PI_BASE_REG+0x0C) + +/* + * PI status (R): [0] DMA busy, [1] IO busy, [2], error + * (W): [0] reset controller (and abort current op), [1] clear intr + */ + +#define PI_BSD_DOM1_LAT_REG (PI_BASE_REG+0x14) + +/* PI dom1 pulse width (R/W): [7:0] domain 1 device R/W strobe pulse width */ +#define PI_BSD_DOM1_PWD_REG (PI_BASE_REG+0x18) + +/* PI dom1 page size (R/W): [3:0] domain 1 device page size */ +#define PI_BSD_DOM1_PGS_REG (PI_BASE_REG+0x1C) /* page size */ + +/* PI dom1 release (R/W): [1:0] domain 1 device R/W release duration */ +#define PI_BSD_DOM1_RLS_REG (PI_BASE_REG+0x20) +/* PI dom2 latency (R/W): [7:0] domain 2 device latency */ +#define PI_BSD_DOM2_LAT_REG (PI_BASE_REG+0x24) /* Domain 2 latency */ + +/* PI dom2 pulse width (R/W): [7:0] domain 2 device R/W strobe pulse width */ +#define PI_BSD_DOM2_PWD_REG (PI_BASE_REG+0x28) /* pulse width */ + +/* PI dom2 page size (R/W): [3:0] domain 2 device page size */ +#define PI_BSD_DOM2_PGS_REG (PI_BASE_REG+0x2C) /* page size */ + +/* PI dom2 release (R/W): [1:0] domain 2 device R/W release duration */ +#define PI_BSD_DOM2_RLS_REG (PI_BASE_REG+0x30) /* release duration */ + + +#define PI_DOMAIN1_REG PI_BSD_DOM1_LAT_REG +#define PI_DOMAIN2_REG PI_BSD_DOM2_LAT_REG + + +#define PI_STATUS_ERROR 0x04 +#define PI_STATUS_IO_BUSY 0x02 +#define PI_STATUS_DMA_BUSY 0x01 + +#define DPC_START (DP_BASE_REG + 0x00) +#define DPC_END (DP_BASE_REG + 0x04) +#define DPC_CURRENT (DP_BASE_REG + 0x08) +#define DPC_STATUS (DP_BASE_REG + 0x0C) +#define DPC_CLOCK (DP_BASE_REG + 0x10) +#define DPC_BUFBUSY (DP_BASE_REG + 0x14) +#define DPC_PIPEBUSY (DP_BASE_REG + 0x18) +#define DPC_TMEM (DP_BASE_REG + 0x1C) + +#define VI_CONTROL (VI_BASE_REG + 0x00) +#define VI_FRAMEBUFFER (VI_BASE_REG + 0x04) +#define VI_WIDTH (VI_BASE_REG + 0x08) +#define VI_V_INT (VI_BASE_REG + 0x0C) +#define VI_CUR_LINE (VI_BASE_REG + 0x10) +#define VI_TIMING (VI_BASE_REG + 0x14) +#define VI_V_SYNC (VI_BASE_REG + 0x18) +#define VI_H_SYNC (VI_BASE_REG + 0x1C) +#define VI_H_SYNC2 (VI_BASE_REG + 0x20) +#define VI_H_LIMITS (VI_BASE_REG + 0x24) +#define VI_COLOR_BURST (VI_BASE_REG + 0x28) +#define VI_H_SCALE (VI_BASE_REG + 0x2C) +#define VI_VSCALE (VI_BASE_REG + 0x30) + +#define PHYS_TO_K0(x) ((u32)(x)|0x80000000) /* physical to kseg0 */ +#define K0_TO_PHYS(x) ((u32)(x)&0x1FFFFFFF) /* kseg0 to physical */ +#define PHYS_TO_K1(x) ((u32)(x)|0xA0000000) /* physical to kseg1 */ +#define K1_TO_PHYS(x) ((u32)(x)&0x1FFFFFFF) /* kseg1 to physical */ + +#define IO_READ(addr) (*(volatile u32*)PHYS_TO_K1(addr)) +#define IO_WRITE(addr,data) (*(volatile u32*)PHYS_TO_K1(addr)=(u32)(data)) + +#define FRAM_EXECUTE_CMD 0xD2000000 +#define FRAM_STATUS_MODE_CMD 0xE1000000 +#define FRAM_ERASE_OFFSET_CMD 0x4B000000 +#define FRAM_WRITE_OFFSET_CMD 0xA5000000 +#define FRAM_ERASE_MODE_CMD 0x78000000 +#define FRAM_WRITE_MODE_CMD 0xB4000000 +#define FRAM_READ_MODE_CMD 0xF0000000 + +#define FRAM_STATUS_REG 0xA8000000 +#define FRAM_COMMAND_REG 0xA8010000 + +int getSRAM( uint8_t *buffer, int size); +int getEeprom( uint8_t *buffer); + +int setSRAM( uint8_t *buffer, int size); +int setEeprom( uint8_t *buffer); + + + + #endif diff --git a/src/flashcart/ed64/types.h b/src/flashcart/ed64/types.h new file mode 100644 index 00000000..625c877b --- /dev/null +++ b/src/flashcart/ed64/types.h @@ -0,0 +1,36 @@ +/* + * File: types.h + * Author: KRIK + * + * Created on 16 ΐοπελό 2011 γ., 2:24 + */ + +#include + +#ifndef _TYPES_H +#define _TYPES_H + +#define u8 unsigned char +#define u16 unsigned short +#define u32 unsigned long +#define u64 unsigned long long + +#define vu8 volatile unsigned char +#define vu16 volatile unsigned short +#define vu32 volatile unsigned long +#define vu64 volatile unsigned long long + +#define s8 signed char +#define s16 short +#define s32 long +#define s64 long long + + +typedef volatile uint64_t sim_vu64; +typedef volatile uint64_t sim_vu64; +typedef unsigned int sim_u32; +typedef uint64_t sim_u64; + + +#endif /* _TYPES_H */ +