From f052cb191b019ccc22a8647e9f5141b0f987ff55 Mon Sep 17 00:00:00 2001 From: Robin Jones Date: Tue, 14 Nov 2023 14:20:16 +0000 Subject: [PATCH] Add save fixes Changes from https://github.com/ariahiro64/N64FlashcartMenu/commit/96efc3824e20096dd7f1e28b0e48b1539eb5de65 --- src/flashcart/ed64/ed64.c | 19 +- src/flashcart/ed64/ed64_ll.c | 411 ++++++++++++++--------------------- src/flashcart/ed64/ed64_ll.h | 22 +- 3 files changed, 184 insertions(+), 268 deletions(-) diff --git a/src/flashcart/ed64/ed64.c b/src/flashcart/ed64/ed64.c index 666e45d9..b32543e1 100644 --- a/src/flashcart/ed64/ed64.c +++ b/src/flashcart/ed64/ed64.c @@ -45,7 +45,7 @@ static flashcart_err_t ed64_init (void) { // find the path to last save if (file_exists(strip_sd_prefix(current_state.last_save_path))) { - int save_size = file_get_size(strip_sd_prefix(current_state.last_save_path)); + int save_size = file_get_size(current_state.last_save_path); if ((f_open(&fil, strip_sd_prefix(current_state.last_save_path), FA_CREATE_ALWAYS | FA_READ | FA_WRITE)) != FR_OK) { return FLASHCART_ERR_LOAD; @@ -59,9 +59,6 @@ static flashcart_err_t ed64_init (void) { current_state.is_fram_save_type = false; ed64_state_save(¤t_state); } - else if (save_size > KiB(32)) { // sram 128 - ed64_ll_get_sram(cartsave_data, save_size); - } else if (save_size > KiB(2)) { // sram ed64_ll_get_sram(cartsave_data, save_size); } @@ -125,6 +122,8 @@ static flashcart_err_t ed64_load_rom (char *rom_path, flashcart_progress_callbac return FLASHCART_ERR_LOAD; } + // FIXME: is this actually needed? + /* if (rom_size == MiB(64)) { ed64_save_type_t type = ed64_ll_get_save_type(); switch (type) { @@ -141,6 +140,7 @@ static flashcart_err_t ed64_load_rom (char *rom_path, flashcart_progress_callbac break; } } + */ size_t sdram_size = rom_size; @@ -216,7 +216,7 @@ static flashcart_err_t ed64_load_save (char *save_path) { return FLASHCART_ERR_LOAD; } - size_t save_size = file_get_size(strip_sd_prefix(save_path)); + size_t save_size = file_get_size(save_path); uint8_t cartsave_data[save_size]; if (f_read(&fil, cartsave_data, save_size, &br) != FR_OK) { @@ -224,7 +224,7 @@ static flashcart_err_t ed64_load_save (char *save_path) { return FLASHCART_ERR_LOAD; } - if (f_close(&fil) != FR_OK) { + if (br != save_size) { return FLASHCART_ERR_LOAD; } @@ -237,19 +237,16 @@ static flashcart_err_t ed64_load_save (char *save_path) { ed64_ll_set_eeprom(cartsave_data, save_size); break; case SAVE_TYPE_SRAM: - ed64_ll_set_sram(cartsave_data, save_size); case SAVE_TYPE_SRAM_128K: - ed64_ll_set_sram_128(cartsave_data, KiB(128)); + ed64_ll_set_sram(cartsave_data, save_size); break; case SAVE_TYPE_FLASHRAM: - ed64_ll_set_fram(cartsave_data, KiB(128)); + ed64_ll_set_fram(cartsave_data, save_size); // a cold and warm boot has no way of seeing save types and most types can be determined by size // this tells the cart to use flash instead of sram 128 since they are the same size current_state.is_fram_save_type = true; ed64_state_save(¤t_state); break; - case SAVE_TYPE_DD64_CART_PORT: - break; default: break; } diff --git a/src/flashcart/ed64/ed64_ll.c b/src/flashcart/ed64/ed64_ll.c index 23b2fe02..faea332d 100644 --- a/src/flashcart/ed64/ed64_ll.c +++ b/src/flashcart/ed64/ed64_ll.c @@ -3,7 +3,16 @@ #include "utils/utils.h" #include "ed64_ll.h" +//FIXME find a better solution, perferably a libdragon one +void sleep (unsigned long ms); +void sleep (unsigned long ms) { + + unsigned long current_ms = get_ticks_ms(); + + while (get_ticks_ms() - current_ms < ms); + +} /* ED64 configuration registers base address */ #define ED64_CONFIG_REGS_BASE (0xA8040000) @@ -26,13 +35,10 @@ typedef enum { } ed64_registers_t; void pi_initialize (void); +void pi_dma_wait (void); void pi_initialize_sram (void); -void pi_dma_from_cart (void* dest, void* src, unsigned long size); -void pi_dma_to_cart (void* dest, void* src, unsigned long size); void pi_dma_from_sram (void *dest, unsigned long offset, unsigned long size); void pi_dma_to_sram (void* src, unsigned long offset, unsigned long size); -void pi_dma_from_cart_safe (void *dest, void *src, unsigned long size); - void ed64_ll_set_sdcard_timing (void); @@ -44,20 +50,8 @@ void ed64_ll_set_sdcard_timing (void); #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); @@ -66,6 +60,9 @@ 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; + ed64_save_type_t ed64_ll_get_save_type (void) { @@ -128,14 +125,47 @@ void ed64_ll_set_sram_bank (uint8_t bank) { } +// FIXME Id like to use libdragon's equivelant for this +void _data_cache_invalidate_all (void) { + asm( + "li $8,0x80000000;" + "li $9,0x80000000;" + "addu $9,$9,0x1FF0;" + "cacheloop:;" + "cache 1,0($8);" + "cache 1,16($8);" + "cache 1,32($8);" + "cache 1,48($8);" + "cache 1,64($8);" + "cache 1,80($8);" + "cache 1,96($8);" + "addu $8,$8,112;" + "bne $8,$9,cacheloop;" + "cache 1,0($8);" + : // no outputs + : // no inputs + : "$8", "$9" // trashed registers + ); +} + + +// register related functions + +// FIXME i dont actually think the alt64 names are do what they are saying they are doing +// a proper rename is in order? void pi_initialize (void) { - dma_wait(); + pi_dma_wait(); io_write(PI_STATUS_REG, 0x03); } +void pi_dma_wait (void) { + while (io_read(PI_STATUS_REG) & (PI_STATUS_IO_BUSY | PI_STATUS_DMA_BUSY)); + +} + // Inits PI for sram transfer void pi_initialize_sram (void) { @@ -149,251 +179,25 @@ void pi_initialize_sram (void) { void pi_dma_from_sram (void *dest, unsigned long offset, unsigned long size) { io_write(PI_DRAM_ADDR_REG, K1_TO_PHYS(dest)); - io_write(PI_CART_ADDR_REG, (0xA8000000 + offset)); + io_write(PI_CART_ADDR_REG, (PI_SAVE_ADDR + offset)); asm volatile ("" : : : "memory"); io_write(PI_WR_LEN_REG, (size - 1)); asm volatile ("" : : : "memory"); } - void pi_dma_to_sram (void *src, unsigned long offset, unsigned long size) { - dma_wait(); + pi_dma_wait(); 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_CART_ADDR_REG, (PI_SAVE_ADDR + offset)); + _data_cache_invalidate_all(); io_write(PI_RD_LEN_REG, (size - 1)); } -void pi_dma_from_cart (void* dest, void* src, unsigned long size) { - - dma_wait(); - - 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_dma_to_cart (void* dest, void* src, unsigned long size) { - - dma_wait(); - - 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_dma_from_cart_safe (void *dest, void *src, unsigned long size) { - - if (!dest || !src || !size) return; - - unsigned long unalignedSrc = ((unsigned long)src) % 2; - unsigned long unalignedDest = ((unsigned long)dest) % 8; - - //FIXME: Do i really need to check if size is 16bit aligned? - if (!unalignedDest && !unalignedSrc && !(size % 2)) { - pi_dma_from_cart(dest, src, size); - dma_wait(); - - return; - } - - void* newSrc = (void*)(((unsigned long)src) - unalignedSrc); - unsigned long newSize = (size + unalignedSrc) + ((size + unalignedSrc) % 2); - - unsigned char *buffer = memalign(8, newSize); - pi_dma_from_cart(buffer, newSrc, newSize); - dma_wait(); - - memcpy(dest, (buffer + unalignedSrc), size); - - free(buffer); - -} - - -int ed64_ll_get_sram_128 (uint8_t *buffer, int size) { - - dma_wait(); - - 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); - - dma_wait(); - - pi_initialize(); - - dma_wait(); - - // Offset Large RAM size 128KiB with a 16KiB nudge to allocate enough space - // We do this because 128Kib is not recognised and a 32KiB allocates too little - pi_dma_from_sram(buffer, -(size - KiB(16)), size); - - dma_wait(); - - 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 ed64_ll_get_sram (uint8_t *buffer, int size) { - - dma_wait(); - - 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); - - dma_wait(); - - pi_initialize(); - - dma_wait(); - - pi_dma_from_sram(buffer, 0, size) ; - - dma_wait(); - - 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 ed64_ll_get_eeprom (uint8_t *buffer, int size) { - - int blocks=size/8; - for( int b = 0; b < blocks; b++ ) { - eeprom_read( b, &buffer[b * 8] ); - } - - return 1; - -} - - -int ed64_ll_get_fram (uint8_t *buffer, int size) { - - ed64_ll_set_save_type(SAVE_TYPE_SRAM_128K); //2 - dma_wait(); - - ed64_ll_get_sram_128(buffer, size); - data_cache_hit_writeback_invalidate(buffer, size); - - dma_wait(); - ed64_ll_set_save_type(SAVE_TYPE_FLASHRAM); - - return 1; - -} - -/* -sram upload -*/ - - -int ed64_ll_set_sram_128 (uint8_t *buffer, int size) { - - //half working - dma_wait(); - //Timing - pi_initialize_sram(); - - //Readmode - pi_initialize(); - - data_cache_hit_writeback_invalidate(buffer,size); - dma_wait(); - - // Offset Large RAM size 128KiB with a 16KiB nudge to allocate enough space - // We do this because 128Kib is not recognised and a 32KiB allocates too little - pi_dma_to_sram(buffer, -(size - KiB(16)), size); - data_cache_hit_writeback_invalidate(buffer,size); - - //Wait - dma_wait(); - //Restore evd Timing - ed64_ll_set_sdcard_timing(); - - return 1; - -} - - -int ed64_ll_set_sram (uint8_t *buffer, int size) { - - //half working - dma_wait(); - //Timing - pi_initialize_sram(); - - //Readmode - pi_initialize(); - - data_cache_hit_writeback_invalidate(buffer,size); - dma_wait(); - - pi_dma_to_sram(buffer, 0, size); - data_cache_hit_writeback_invalidate(buffer,size); - - //Wait - dma_wait(); - //Restore evd Timing - ed64_ll_set_sdcard_timing(); - - return 1; - -} - - -int ed64_ll_set_eeprom (uint8_t *buffer, int size) { - - int blocks=size/8; - for( int b = 0; b < blocks; b++ ) { - eeprom_write( b, &buffer[b * 8] ); - } - - return 1; - -} - -int ed64_ll_set_fram (uint8_t *buffer, int size) { - - ed64_ll_set_save_type(SAVE_TYPE_SRAM_128K); - dma_wait(); - - ed64_ll_set_sram_128(buffer, size); - data_cache_hit_writeback_invalidate(buffer, size); - - dma_wait(); - ed64_ll_set_save_type(SAVE_TYPE_FLASHRAM); - - return 1; - -} - - void ed64_ll_set_sdcard_timing (void) { io_write(PI_BSD_DOM1_LAT_REG, 0x40); @@ -407,3 +211,116 @@ void ed64_ll_set_sdcard_timing (void) { io_write(PI_BSD_DOM2_RLS_REG, 0x03); } + + +void ed64_ll_get_sram (uint8_t *buffer, int size) { + + pi_initialize_sram(); + + dma_wait(); + + pi_initialize(); + + sleep(250); + + // checks if the save isnt large and if so grabs it from the large save area + if(size == KiB(32)) + { + pi_dma_from_sram(buffer, 0, size) ; + } + else + { + pi_dma_from_sram(buffer, -KiB(64), size) ; + } + + dma_wait(); + + ed64_ll_set_sdcard_timing(); + +} + +void ed64_ll_get_eeprom (uint8_t *buffer, int size) { + + int blocks=size/8; + for( int b = 0; b < blocks; b++ ) { + eeprom_read( b, &buffer[b * 8] ); + } + +} + + +void ed64_ll_get_fram (uint8_t *buffer, int size) { + + ed64_ll_set_save_type(SAVE_TYPE_SRAM_128K); //2 + sleep(512); + + data_cache_hit_writeback_invalidate(buffer,size); + dma_wait(); + + ed64_ll_get_sram(buffer, size); + + sleep(512); + ed64_ll_set_save_type(SAVE_TYPE_FLASHRAM); + +} + +/* +sram upload +*/ + + +void ed64_ll_set_sram (uint8_t *buffer, int size) { + + pi_dma_wait(); + + //Timing + pi_initialize_sram(); + + //Readmode + pi_initialize(); + + data_cache_hit_writeback_invalidate(buffer,size); + dma_wait(); + + // checks if you are no using a large save and if you are puts it in the large save area + if(size == KiB(32)) + { + pi_dma_to_sram(buffer, 0, size) ; + } + else + { + pi_dma_to_sram(buffer, -KiB(64), size) ; + } + + //Wait + pi_dma_wait(); + + //Restore evd Timing + ed64_ll_set_sdcard_timing(); + +} + + +void ed64_ll_set_eeprom (uint8_t *buffer, int size) { + + int blocks=size/8; + for( int b = 0; b < blocks; b++ ) { + eeprom_write( b, &buffer[b * 8] ); + } + +} + +void ed64_ll_set_fram (uint8_t *buffer, int size) { + + ed64_ll_set_save_type(SAVE_TYPE_SRAM_128K); + sleep(512); + + data_cache_hit_writeback_invalidate(buffer,size); + dma_wait(); + + ed64_ll_set_sram(buffer, size); + + sleep(512); + ed64_ll_set_save_type(SAVE_TYPE_FLASHRAM); + +} diff --git a/src/flashcart/ed64/ed64_ll.h b/src/flashcart/ed64/ed64_ll.h index e4436262..2ea4ab4b 100644 --- a/src/flashcart/ed64/ed64_ll.h +++ b/src/flashcart/ed64/ed64_ll.h @@ -12,11 +12,13 @@ #include #include +/* ED64 save location base address */ +#define PI_SAVE_ADDR 0xA8000000 + // FIXME: redefined because its in a .c instead of a .h #define PI_BASE_REG 0x04600000 -/////////////////////////////////////////////////////// -#define PIF_RAM_START 0x1FC007C0 +/////////////////////////////////////////////////////// #define PI_STATUS_ERROR 0x04 #define PI_STATUS_IO_BUSY 0x02 #define PI_STATUS_DMA_BUSY 0x01 @@ -65,19 +67,19 @@ typedef enum { #define ROM_ADDRESS (0xB0000000) /* Save functions */ +void pi_initialize_sram (void); +void _data_cache_invalidate_all (void); void ed64_ll_set_sram_bank (uint8_t bank); ed64_save_type_t ed64_ll_get_save_type (); void ed64_ll_set_save_type (ed64_save_type_t type); -int ed64_ll_get_sram_128 (uint8_t *buffer, int size); -int ed64_ll_get_sram (uint8_t *buffer, int size); -int ed64_ll_get_eeprom (uint8_t *buffer, int size); -int ed64_ll_get_fram (uint8_t *buffer, int size); +void ed64_ll_get_sram (uint8_t *buffer, int size); +void ed64_ll_get_eeprom (uint8_t *buffer, int size); +void ed64_ll_get_fram (uint8_t *buffer, int size); -int ed64_ll_set_sram_128 (uint8_t *buffer, int size); -int ed64_ll_set_sram (uint8_t *buffer, int size); -int ed64_ll_set_eeprom (uint8_t *buffer, int size); -int ed64_ll_set_fram (uint8_t *buffer, int size); +void ed64_ll_set_sram (uint8_t *buffer, int size); +void ed64_ll_set_eeprom (uint8_t *buffer, int size); +void ed64_ll_set_fram (uint8_t *buffer, int size); /** @} */ /* ed64 */ #endif