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