mirror of
https://github.com/Polprzewodnikowy/SummerCart64.git
synced 2025-04-25 03:51:35 +02:00
[SC64][SW] Implement FlashRAM timings emulation and add a fake variant of FlashRAM
This commit is contained in:
parent
8393963650
commit
f546e5d17d
docs
sw
bootloader/src
controller/src
deployer/src
@ -133,9 +133,10 @@ type: *enum* | default: `0`
|
||||
- `4` - FlashRAM 1 Mib save is enabled
|
||||
- `5` - SRAM 768 kib save is enabled
|
||||
- `6` - SRAM 1 Mib save is enabled
|
||||
- `7` - FakeFlashRAM 1 Mib save is enabled (write/erase timings are not emulated and erase before write is not required)
|
||||
|
||||
Use this setting for selecting save type that will be emulated. Only one save type can be enabled.
|
||||
Any successful write to this config will disable automatic save writeback to USB or SD card when previously enabled.
|
||||
Any successful write to this config will disable automatic save writeback to the USB or SD card if previously enabled.
|
||||
|
||||
---
|
||||
|
||||
|
@ -104,7 +104,8 @@ typedef enum {
|
||||
SAVE_TYPE_SRAM = 3,
|
||||
SAVE_TYPE_FLASHRAM = 4,
|
||||
SAVE_TYPE_SRAM_BANKED = 5,
|
||||
SAVE_TYPE_SRAM_1M = 6
|
||||
SAVE_TYPE_SRAM_1M = 6,
|
||||
SAVE_TYPE_FLASHRAM_FAKE = 7,
|
||||
} sc64_save_type_t;
|
||||
|
||||
typedef enum {
|
||||
|
@ -278,6 +278,9 @@ static bool cfg_set_save_type (save_type_t save_type) {
|
||||
case SAVE_TYPE_SRAM_1M:
|
||||
cfg_change_scr_bits(CFG_SCR_SRAM_ENABLED, true);
|
||||
break;
|
||||
case SAVE_TYPE_FLASHRAM_FAKE:
|
||||
cfg_change_scr_bits(CFG_SCR_FLASHRAM_ENABLED, true);
|
||||
break;
|
||||
default:
|
||||
save_type = SAVE_TYPE_NONE;
|
||||
break;
|
||||
|
@ -14,6 +14,7 @@ typedef enum {
|
||||
SAVE_TYPE_FLASHRAM = 4,
|
||||
SAVE_TYPE_SRAM_BANKED = 5,
|
||||
SAVE_TYPE_SRAM_1M = 6,
|
||||
SAVE_TYPE_FLASHRAM_FAKE = 7,
|
||||
__SAVE_TYPE_COUNT
|
||||
} save_type_t;
|
||||
|
||||
|
@ -1,12 +1,18 @@
|
||||
#include <stdint.h>
|
||||
#include "cfg.h"
|
||||
#include "fpga.h"
|
||||
#include "hw.h"
|
||||
#include "timer.h"
|
||||
|
||||
|
||||
#define FLASHRAM_SIZE (128 * 1024)
|
||||
#define FLASHRAM_SECTOR_SIZE (16 * 1024)
|
||||
#define FLASHRAM_PAGE_SIZE (128)
|
||||
#define FLASHRAM_ADDRESS (0x03FE0000UL)
|
||||
#define FLASHRAM_BUFFER_ADDRESS (0x05002C00UL)
|
||||
#define FLASHRAM_SIZE (128 * 1024)
|
||||
#define FLASHRAM_SECTOR_SIZE (16 * 1024)
|
||||
#define FLASHRAM_PAGE_SIZE (128)
|
||||
#define FLASHRAM_ADDRESS (0x03FE0000UL)
|
||||
#define FLASHRAM_BUFFER_ADDRESS (0x05002C00UL)
|
||||
|
||||
#define FLASHRAM_WRITE_TIMING_MS (3)
|
||||
#define FLASHRAM_ERASE_TIMING_MS (200)
|
||||
|
||||
|
||||
typedef enum {
|
||||
@ -16,6 +22,13 @@ typedef enum {
|
||||
OP_WRITE_PAGE
|
||||
} flashram_op_t;
|
||||
|
||||
struct process {
|
||||
bool pending;
|
||||
};
|
||||
|
||||
|
||||
static struct process p;
|
||||
|
||||
|
||||
static flashram_op_t flashram_operation_type (uint32_t scr) {
|
||||
if (!(scr & FLASHRAM_SCR_PENDING)) {
|
||||
@ -38,6 +51,7 @@ void flashram_init (void) {
|
||||
if (fpga_reg_get(REG_FLASHRAM_SCR) & FLASHRAM_SCR_PENDING) {
|
||||
fpga_reg_set(REG_FLASHRAM_SCR, FLASHRAM_SCR_DONE);
|
||||
}
|
||||
p.pending = false;
|
||||
}
|
||||
|
||||
|
||||
@ -53,8 +67,15 @@ void flashram_process (void) {
|
||||
uint8_t write_buffer[FLASHRAM_PAGE_SIZE];
|
||||
|
||||
uint32_t page = ((scr & FLASHRAM_SCR_PAGE_MASK) >> FLASHRAM_SCR_PAGE_BIT);
|
||||
const bool full_emulation = (cfg_get_save_type() != SAVE_TYPE_FLASHRAM_FAKE);
|
||||
|
||||
if (op == OP_WRITE_PAGE) {
|
||||
if (p.pending) {
|
||||
if (timer_countdown_elapsed(TIMER_ID_FLASHRAM)) {
|
||||
p.pending = false;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
} else if (op == OP_WRITE_PAGE) {
|
||||
uint8_t page_buffer[FLASHRAM_PAGE_SIZE];
|
||||
|
||||
uint32_t address = (FLASHRAM_ADDRESS + (page * FLASHRAM_PAGE_SIZE));
|
||||
@ -63,11 +84,24 @@ void flashram_process (void) {
|
||||
fpga_mem_read(address, FLASHRAM_PAGE_SIZE, write_buffer);
|
||||
|
||||
for (int i = 0; i < FLASHRAM_PAGE_SIZE; i++) {
|
||||
write_buffer[i] &= page_buffer[i];
|
||||
if (full_emulation) {
|
||||
write_buffer[i] &= page_buffer[i];
|
||||
} else {
|
||||
write_buffer[i] = page_buffer[i];
|
||||
}
|
||||
}
|
||||
|
||||
fpga_mem_write(address, FLASHRAM_PAGE_SIZE, write_buffer);
|
||||
} else if ((op == OP_ERASE_SECTOR) || (op == OP_ERASE_ALL)) {
|
||||
|
||||
if (full_emulation) {
|
||||
hw_delay_ms(FLASHRAM_WRITE_TIMING_MS);
|
||||
}
|
||||
} else if ((op == OP_ERASE_SECTOR) || (op == OP_ERASE_ALL)) {
|
||||
if (full_emulation) {
|
||||
p.pending = true;
|
||||
timer_countdown_start(TIMER_ID_FLASHRAM, FLASHRAM_ERASE_TIMING_MS);
|
||||
}
|
||||
|
||||
for (int i = 0; i < FLASHRAM_PAGE_SIZE; i++) {
|
||||
write_buffer[i] = 0xFF;
|
||||
}
|
||||
@ -80,6 +114,10 @@ void flashram_process (void) {
|
||||
for (uint32_t offset = 0; offset < erase_size; offset += FLASHRAM_PAGE_SIZE) {
|
||||
fpga_mem_write(address + offset, FLASHRAM_PAGE_SIZE, write_buffer);
|
||||
}
|
||||
|
||||
if (full_emulation) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
fpga_reg_set(REG_FLASHRAM_SCR, FLASHRAM_SCR_DONE);
|
||||
|
@ -176,13 +176,11 @@ static bool sd_acmd (uint8_t acmd, uint32_t arg, rsp_type_t rsp_type, void *rsp)
|
||||
static void sd_dat_start_write (uint32_t count) {
|
||||
uint32_t dat = (((count - 1) << SD_DAT_BLOCKS_BIT) | SD_DAT_START_WRITE | SD_DAT_FIFO_FLUSH);
|
||||
fpga_reg_set(REG_SD_DAT, dat);
|
||||
|
||||
}
|
||||
|
||||
static void sd_dat_start_read (uint32_t count) {
|
||||
uint32_t dat = (((count - 1) << SD_DAT_BLOCKS_BIT) | SD_DAT_START_READ | SD_DAT_FIFO_FLUSH);
|
||||
fpga_reg_set(REG_SD_DAT, dat);
|
||||
|
||||
}
|
||||
|
||||
static dat_status_t sd_dat_status (void) {
|
||||
|
@ -13,6 +13,7 @@ typedef enum {
|
||||
TIMER_ID_SD,
|
||||
TIMER_ID_USB,
|
||||
TIMER_ID_WRITEBACK,
|
||||
TIMER_ID_FLASHRAM,
|
||||
__TIMER_ID_COUNT
|
||||
} timer_id_t;
|
||||
|
||||
|
@ -62,6 +62,10 @@ static save_type_t writeback_get_address_length (uint32_t *address, uint32_t *le
|
||||
*address = SRAM_FLASHRAM_ADDRESS;
|
||||
*length = SRAM_1M_LENGTH;
|
||||
break;
|
||||
case SAVE_TYPE_FLASHRAM_FAKE:
|
||||
*address = SRAM_FLASHRAM_ADDRESS;
|
||||
*length = FLASHRAM_LENGTH;
|
||||
break;
|
||||
default:
|
||||
*address = 0;
|
||||
*length = 0;
|
||||
|
@ -330,6 +330,7 @@ enum SaveType {
|
||||
SramBanked,
|
||||
Sram1m,
|
||||
Flashram,
|
||||
FlashramFake,
|
||||
}
|
||||
|
||||
impl From<n64::SaveType> for SaveType {
|
||||
@ -356,6 +357,7 @@ impl From<SaveType> for sc64::SaveType {
|
||||
SaveType::SramBanked => Self::SramBanked,
|
||||
SaveType::Sram1m => Self::Sram1m,
|
||||
SaveType::Flashram => Self::Flashram,
|
||||
SaveType::FlashramFake => Self::FlashramFake,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -445,6 +445,7 @@ impl SC64 {
|
||||
SaveType::Flashram => (SAVE_ADDRESS, FLASHRAM_LENGTH),
|
||||
SaveType::SramBanked => (SAVE_ADDRESS, SRAM_BANKED_LENGTH),
|
||||
SaveType::Sram1m => (SAVE_ADDRESS, SRAM_1M_LENGTH),
|
||||
SaveType::FlashramFake => (SAVE_ADDRESS, FLASHRAM_LENGTH),
|
||||
};
|
||||
|
||||
if length != save_length {
|
||||
@ -469,6 +470,7 @@ impl SC64 {
|
||||
SaveType::Flashram => (SAVE_ADDRESS, FLASHRAM_LENGTH),
|
||||
SaveType::SramBanked => (SAVE_ADDRESS, SRAM_BANKED_LENGTH),
|
||||
SaveType::Sram1m => (SAVE_ADDRESS, SRAM_1M_LENGTH),
|
||||
SaveType::FlashramFake => (SAVE_ADDRESS, FLASHRAM_LENGTH),
|
||||
};
|
||||
|
||||
self.memory_read_chunked(writer, address, save_length)
|
||||
|
@ -288,6 +288,7 @@ pub enum SaveType {
|
||||
Flashram,
|
||||
SramBanked,
|
||||
Sram1m,
|
||||
FlashramFake,
|
||||
}
|
||||
|
||||
impl Display for SaveType {
|
||||
@ -300,6 +301,7 @@ impl Display for SaveType {
|
||||
Self::SramBanked => "SRAM 768k",
|
||||
Self::Flashram => "FlashRAM 1M",
|
||||
Self::Sram1m => "SRAM 1M",
|
||||
Self::FlashramFake => "FakeFlashRAM 1M"
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -315,6 +317,7 @@ impl TryFrom<u32> for SaveType {
|
||||
4 => Self::Flashram,
|
||||
5 => Self::SramBanked,
|
||||
6 => Self::Sram1m,
|
||||
7 => Self::FlashramFake,
|
||||
_ => return Err(Error::new("Unknown save type code")),
|
||||
})
|
||||
}
|
||||
@ -330,6 +333,7 @@ impl From<SaveType> for u32 {
|
||||
SaveType::Flashram => 4,
|
||||
SaveType::SramBanked => 5,
|
||||
SaveType::Sram1m => 6,
|
||||
SaveType::FlashramFake => 7,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user