Improve worst case saving speeds

This commit is contained in:
Lorenzooone 2023-11-30 12:22:23 +01:00
parent 2a3bd9b97f
commit c3ee0e7ed9

View File

@ -31,14 +31,15 @@
#define BANK_LIMIT (NUM_BANKS * BANK_SIZE)
#endif
uintptr_t bank_check(uintptr_t);
static uintptr_t bank_check(uintptr_t);
static size_t sanitize_save_size(uintptr_t, size_t);
static u8 read_direct_single_byte_save(uintptr_t);
static void write_direct_single_byte_save(uintptr_t, u8);
u8 current_bank;
u8 is_macronix;
IWRAM_CODE void init_bank(){
IWRAM_CODE void init_bank() {
REG_WAITCNT &= NON_SRAM_MASK;
REG_WAITCNT |= SRAM_READING_VALID_WAITCYCLES;
current_bank = NUM_BANKS;
@ -54,7 +55,7 @@ IWRAM_CODE void init_bank(){
#endif
}
IWRAM_CODE uintptr_t bank_check(uintptr_t address){
IWRAM_CODE uintptr_t bank_check(uintptr_t address) {
address %= (NUM_BANKS * BANK_SIZE);
#if IS_FLASH
u8 bank = address / BANK_SIZE;
@ -114,103 +115,110 @@ IWRAM_CODE void write_direct_single_byte_save(uintptr_t address, u8 data) {
}
}
IWRAM_CODE u8 read_byte_save(uintptr_t address){
IWRAM_CODE u8 read_byte_save(uintptr_t address) {
address = bank_check(address);
return read_direct_single_byte_save(address);
}
IWRAM_CODE void write_byte_save(uintptr_t address, u8 data){
IWRAM_CODE u16 read_short_save(uintptr_t address) {
u16 data_out = 0;
copy_save_to_ram(address, (u8*)&data_out, sizeof(u16));
return data_out;
}
IWRAM_CODE u32 read_int_save(uintptr_t address) {
u32 data_out = 0;
copy_save_to_ram(address, (u8*)&data_out, sizeof(u32));
return data_out;
}
IWRAM_CODE void write_byte_save(uintptr_t address, u8 data) {
address = bank_check(address);
write_direct_single_byte_save(address, data);
}
IWRAM_CODE u32 read_int_save(uintptr_t address){
IWRAM_CODE void write_short_save(uintptr_t address, u16 data) {
u16 data_in = data;
copy_ram_to_save((u8*)&data_in, address, sizeof(u16));
}
IWRAM_CODE void write_int_save(uintptr_t address, u32 data) {
u32 data_in = data;
copy_ram_to_save((u8*)&data_in, address, sizeof(u32));
}
IWRAM_CODE size_t sanitize_save_size(uintptr_t address, size_t size) {
address %= NUM_BANKS * BANK_SIZE;
if((address + size) > (NUM_BANKS * BANK_SIZE))
size = (NUM_BANKS * BANK_SIZE) - address;
return size;
}
IWRAM_CODE void copy_save_to_ram(uintptr_t address, u8* destination, size_t size) {
// Sanitize size
size = sanitize_save_size(address, size);
address = bank_check(address);
u32 data_out = 0;
if((address + sizeof(u32)) > BANK_LIMIT) {
for(size_t i = 0; i < sizeof(u32); i++)
data_out += read_byte_save(address + i) << (i*8);
}
else {
for(size_t i = 0; i < sizeof(u32); i++)
data_out += read_direct_single_byte_save(address + i) << (i*8);
}
return data_out;
}
size_t num_banks = (address + size + BANK_SIZE - 1) / BANK_SIZE;
for(size_t n = 0; n < num_banks; n++) {
size_t inner_size = size;
if(n != (num_banks - 1))
inner_size = BANK_SIZE - address;
IWRAM_CODE u16 read_short_save(uintptr_t address){
address = bank_check(address);
u16 data_out = 0;
if((address + sizeof(u16)) > BANK_LIMIT) {
for(size_t i = 0; i < sizeof(u16); i++)
data_out += read_byte_save(address + i) << (i*8);
}
else {
for(size_t i = 0; i < sizeof(u16); i++)
data_out += read_direct_single_byte_save(address + i) << (i*8);
}
return data_out;
}
for(size_t i = 0; i < inner_size; i++)
destination[i] = read_direct_single_byte_save(address + i);
IWRAM_CODE void write_int_save(uintptr_t address, u32 data){
address = bank_check(address);
if((address + sizeof(u32)) > BANK_LIMIT) {
for(size_t i = 0; i < sizeof(u32); i++)
write_byte_save(address + i, (data >> (i*8)) & 0xFF);
}
else {
for(size_t i = 0; i < sizeof(u32); i++)
write_direct_single_byte_save(address + i, (data >> (i*8)) & 0xFF);
if(n != (num_banks - 1)) {
address = bank_check(address + inner_size);
destination += inner_size;
size -= inner_size;
}
}
}
IWRAM_CODE void write_short_save(uintptr_t address, u16 data){
address = bank_check(address);
if((address + sizeof(u16)) > BANK_LIMIT) {
for(size_t i = 0; i < sizeof(u16); i++)
write_byte_save(address + i, (data >> (i*8)) & 0xFF);
}
else {
for(size_t i = 0; i < sizeof(u16); i++)
write_direct_single_byte_save(address + i, (data >> (i*8)) & 0xFF);
}
}
IWRAM_CODE void copy_ram_to_save(u8* base_address, uintptr_t save_address, size_t size) {
// Sanitize size
size = sanitize_save_size(save_address, size);
IWRAM_CODE void copy_save_to_ram(uintptr_t base_address, u8* new_address, size_t size){
base_address = bank_check(base_address);
if((base_address + size) > BANK_LIMIT) {
for(size_t i = 0; i < size; i++)
new_address[i] = read_byte_save(base_address + i);
}
else {
for(size_t i = 0; i < size; i++)
new_address[i] = read_direct_single_byte_save(base_address + i);
}
}
IWRAM_CODE void copy_ram_to_save(u8* base_address, uintptr_t save_address, size_t size){
save_address = bank_check(save_address);
if((save_address + size) > BANK_LIMIT) {
for(size_t i = 0; i < size; i++)
write_byte_save(save_address + i, base_address[i]);
}
else {
for(size_t i = 0; i < size; i++)
size_t num_banks = (save_address + size + BANK_SIZE - 1) / BANK_SIZE;
for(size_t n = 0; n < num_banks; n++) {
size_t inner_size = size;
if(n != (num_banks - 1))
inner_size = BANK_SIZE - save_address;
for(size_t i = 0; i < inner_size; i++)
write_direct_single_byte_save(save_address + i, base_address[i]);
if(n != (num_banks - 1)) {
save_address = bank_check(save_address + inner_size);
base_address += inner_size;
size -= inner_size;
}
}
}
IWRAM_CODE u8 is_save_correct(u8* base_address, uintptr_t save_address, size_t size) {
// Sanitize size
size = sanitize_save_size(save_address, size);
save_address = bank_check(save_address);
if((save_address + size) > BANK_LIMIT) {
for(size_t i = 0; i < size; i++)
if(read_byte_save(save_address + i) != base_address[i])
return 0;
}
else {
for(size_t i = 0; i < size; i++)
size_t num_banks = (save_address + size + BANK_SIZE - 1) / BANK_SIZE;
for(size_t n = 0; n < num_banks; n++) {
size_t inner_size = size;
if(n != (num_banks - 1))
inner_size = BANK_SIZE - save_address;
for(size_t i = 0; i < inner_size; i++)
if(read_direct_single_byte_save(save_address + i) != base_address[i])
return 0;
if(n != (num_banks - 1)) {
save_address = bank_check(save_address + inner_size);
base_address += inner_size;
size -= inner_size;
}
}
return 1;
}